k8s 部署cassandra 镜像制作

内置初始权限

​ 最近有个新的需求,在k8s环境上部署一个cassandra集群,并能对外提供使用,要求是要内置一张表。今日成功做完,记录一下踩坑历史。

​ 先介绍下环境,有一个k8s集群,包括一个master节点和三个worker节点。kubernetes版本: 1.16.9。docker版本:docker-ce-18.09.9。

​ 首先是通过yaml文件把Cassandra集群部署出来。kubernetes官网有cassandra的部署步骤(https://kubernetes.io/zh/docs/tutorials/stateful-application/cassandra/)。这里贴出yaml:

#设置一个nodeport service用于对外提供服务
kind: Service
apiVersion: v1
metadata:
  namespace: firstrain #命名空间
  name: cassandra-client
  labels:
    app: cassandra
spec:
  type: NodePort
  ports:
   - name: main
     protocol: TCP
     port: 9042
     targetPort: 9042
     nodePort:  
  selector:
    app: cassandra
---
#设置一个无头服务用于集群内部通信
apiVersion: v1
kind: Service
metadata:
  labels:
    app: cassandra-headless
  namespace: firstrain
  name: cassandra-headless
spec:
  publishNotReadyAddresses: true #使用StatefulSet的无头服务来传播其Pod的SRV记录,而不考虑它们是否准备就绪,以便于同行发现。
  clusterIP: None
  ports:
  - port: 9042
  selector:
    app: cassandra
---
使用有状态应用部署cassandra
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: cassandra
  namespace: firstrain
  labels:
    app: cassandra
spec:
  replicas: 3 #集群个数
  serviceName: cassandra-headless
  selector:
    matchLabels:
      app: cassandra
  template:
    metadata:
      labels:
        app: cassandra
    spec:
      terminationGracePeriodSeconds: 1800 #terminationGracePeriodSeconds等待时间后,K8S会强制结束老POD
      containers:
      - name: cassandra
        image: gcr.io/google-samples/cassandra:v14 #此处请修改自己harbor镜像仓库的镜像
        imagePullPolicy: Always
        resources:
          requests:
            memory: "2Gi"
            cpu: "1000m"
          limits:
            memory: "2Gi"
            cpu: "1000m"
        ports:
        - containerPort: 7000
          name: intra-node
        - containerPort: 7001
          name: tls-intra-node
        - containerPort: 7199
          name: jmx
        - containerPort: 9042
          name: cql
        securityContext:
          capabilities:
            add:
              - IPC_LOCK
        lifecycle:
          preStop:
            exec:
              command: 
              - /bin/sh
              - -c
              - nodetool drain
        env:
          - name: MAX_HEAP_SIZE
            value: 512M
          - name: HEAP_NEWSIZE
            value: 100M
          - name: CASSANDRA_SEEDS #seed节点,格式为:pod名称.无头服务名称.命名空间.svc.cluster.local。可只指定一个
            value: "cassandra-0.cassandra-headless.firstrain.svc.cluster.local"
          - name: CASSANDRA_CLUSTER_NAME
            value: "Cassandra"
          - name: CASSANDRA_DC
            value: "DC1"
          - name: CASSANDRA_RACK
            value: "Rack1"
          - name: POD_IP
            valueFrom:
              fieldRef:
                fieldPath: status.podIP
        readinessProbe: # 存活探针
          exec:
            command:
            - /bin/bash
            - -c
            - /ready-probe.sh
          initialDelaySeconds: 15
          timeoutSeconds: 5
        volumeMounts:
        - name: cassandra-data
          mountPath: /cassandra_data
  #使用pvc
  volumeClaimTemplates:
  - metadata:
      name: cassandra-data
      labels:
        type: stateful
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: storageclass-default
      resources:
        requests:
          storage: 10Gi

kubectl apply -f cassandra-create.yaml成功创建出一个statefulset应用,使用kubectl get po -n firstrain可查看到创建的3个容器,kubectl get svc -n fristran 查看随机生成的随机nodeport端口,使用Nosql manager for Cassandra连接集群发现不需要用户名即可登陆。

使用kubectl exec -it cassandra-0 -n firstrain bash进入容器,cassandra的配置文件位于/etc/cassandra/cassandra.yaml。配置文件已写清楚,因此改变authenticator值为PasswordAuthenticator即可。

# Authentication backend, implementing IAuthenticator; used to identify users
# Out of the box, Cassandra provides org.apache.cassandra.auth.{AllowAllAuthenticator,
# PasswordAuthenticator}.
#
# - AllowAllAuthenticator performs no checks - set it to disable authentication.
# - PasswordAuthenticator relies on username/password pairs to authenticate
#   users. It keeps usernames and hashed passwords in system_auth.credentials table.
#   Please increase system_auth keyspace replication factor if you use this authenticator.
#   If using PasswordAuthenticator, CassandraRoleManager must also be used (see below)
authenticator: AllowAllAuthenticator

由于该容器使用的ubuntu,内部无vim等基础命令。在k8s master集群中使用kubectl cp firstrain/cassandra-0:/etc/cassandra/cassandra.yaml /home/cassandra.yaml从容器中拷贝出该文件,改变其值。然后使用dockerfile构建初步镜像以做尝试。将cassandra.yaml和DockerFile放在同一个文件夹下。构建镜像:docker build -t cassandra:v14-user .

以下为DockerFile。

FROM gcr.io/google-samples/cassandra:v14
ADD cassandra.yaml /etc/cassandra/cassandra.yaml

将构建的镜像上传到harbor中,接下来修改创建cassandra集群的yaml镜像源。在创建前使用kubectl delete -f cassandra-create.yaml删除之前创建的资源。pvc需自己手动删除。

然后kubectl apply -f cassandra-create.yaml创建集群,再次使用客户端连接cassandr集群,此时会连接失败,因为未指定用户名密码

在这里插入图片描述

cassandra镜像默认的用户名和密码为:-u cassandra -p cassandra。

内置keyspaces

​ 接下来要实现内置keyspaces,

一、初步想法

​ 在创建集群是指定cassandra的数据目录为/cassandra_data。进入集群内部即可查看到根目录下的/cassandra_data。data目录下即为keyspaces,因此只要在构建镜像时在/cassandra_data/data目录中打入一个目录seaweedfs,那么该镜像即可内置seaweedfs库。这次省去打镜像和测试步骤,结果不成功,搭建出来的cassandra集群无seaweedfs库。通过docker inspect 镜像发现在创建容器时运行了run.sh的脚本

初步怀疑是否时run.sh的脚本中执行了初始化数据库的命令。将run.sh脚本拷贝出来查看后发现只在最后一步执行了一个脚本

在这里插入图片描述
在这里插入图片描述

查看对应位置发现是:/usr/local/apache-cassandra-3.11.2/bin/cassandra下,查看该脚本也未发现初始化数据库命令。

二 、安装环境

​ 接下来想法:试图通过cqlsh命令添加keyspaces,但是该容器内并未有python环境。

​ 首先是打算通过二进制包的方式在制作镜像时打进去,但是在执行make & make install命令时缺少gcc的依赖,而gcc依赖又需要npm依赖,这些在容器中均没有,因此考虑第二种方式,因为容器能够联网,因此改变方向,在线安装。

构建的容器使用的时ubuntu,因此安装方式为apt-get,apt-get的镜像源地址为/etc/apt/sources.list,默认使用的时debain源,在国外,速度很慢。要改镜像源首先要apt-get update,然后apt-get install -y vim,之后更换镜像,这里推荐使用清华的源,不建议阿里云的,具体原因时由于在构建镜像安装python2.7时会有依赖错误的情况。

deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial main restricted
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates main restricted
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial universe
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates universe
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-updates multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-backports main restricted universe multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security main restricted
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security universe
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ xenial-security multiverse

更新了sources.list后还要再执行一遍apt-get update,之后即可安装python环境apt-get install python2.7apt-get install python-pip

安装好环境后执行cqlsh,报如下错误,缺少cqlshlib的依赖包。
在这里插入图片描述

第一反应肯定是pip安一个,pip install cqlshlib报错如下

在这里插入图片描述

之后我通过dockerhub的Cassandra镜像启动了一个容器,从里面拷贝了出cqllib包,然后倒入到容器中,依旧不能解决模块缺失问题。再stack overflow中也未找到解决方案,同事说缺少cqlsh。使用** pip install cqlsh**解决模块缺失问题。

nodetool status查看集群ip

在这里插入图片描述

cqlsh 179.20.2.182 -u cassandra -p cassandra连接其中一个,报错如下
在这里插入图片描述
cqlsh 179.20.2.182 -u cassandra -p cassandra --cqlversion=3.4.4指定cqlsh版本即可,成功执行sql

(img-zLPtnnNL-1599235516834)(image/Untitled/image-20200904234057072.png)]

三,内置keyspaces

在容器构建时会执行run.sh脚本,因此我们在run.sh中插入一个sql文件并执行,即可完成keyspaces的构建。

在启动服务前异步执行一个initdb.sh的脚本,由于cql不能通过管道命令执行sql语句,只能通过文件执行,因此需要再写一个sql文件。

在这里插入图片描述

#!/bin/bash

  # Create default keyspace for single node cluster
  CQL="cqlsh localhost -u cassandra -p cassandra --cqlversion=3.4.4  --file="/home/seaweedfs.sql""
  echo "start"
  until $CQL ; do
    echo "cqlsh: Cassandra is unavailable - retry later"
    sleep 2
  done &

四、构建镜像

这一步也是踩过很多坑。先贴Dockerfile

FROM 10.0.100.59:5000/cassandra:v14

RUN rm -rf /etc/apt/sources.list 

ADD cassandra.yaml /etc/cassandra/cassandra.yaml

COPY sources.list /etc/apt/

RUN apt-get update; exit 0 

RUN apt-get install -y gnupg2 --allow-unauthenticated \
    && apt-get -f install \
    && apt-get install -y vim --allow-unauthenticated \
    && apt-get install -y python2.7 --allow-unauthenticated \
    && apt-get install -y python-pip --allow-unauthenticated \
    && pip install cqlsh \
    && rm -rf /usr/local/bin/cqlsh

RUN rm -rf /usr/local/bin/cqlsh

COPY cqlsh /usr/local/bin/

RUN chown -R root:staff /usr/local/bin/cqlsh && chmod 755 /usr/local/bin/cqlsh

将需要的文件拷贝其中并授权。

source.list:镜像源。这一步踩坑在于使用了阿里的镜像源后,apt-get install python2.7会有依赖错误,具体原因未知。

使用apt-get update,这一步踩坑点在于apt-get update过程中会有不影响的错误,需在后面加入;exit 0来忽略错误。

使用-y参数时请在后面加上–allow-unauthenticated否则会报无权限错误。

上面三个RUN命令请不要合再一起写,否则会报错如下,意思是你使用的镜像源未被认证,当单独执行apt-get update时在更新仓库时会自动注册上去。

在这里插入图片描述

之后成功build镜像,验证成功,内置了一个keyspaces
cqlsh中修改默认cqlversion=3.4.4并授权

涉及命令

# kubectl cp 源文件 目标文件。容器与本机文件可互拷,容器需指定namespace:namespace/pod name:拷贝位置
kubectl cp /root/cassandra.yaml firstrain/cassandra-0:/opt/cassandra.yaml

#查看容器的元数据
docker inspect images

#构建容器,指定name:tag。
docker build -t cassandra:v14-mine

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐