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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 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 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 containers: - name: cassandra image: gcr.io/google-samples/cassandra:v14 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 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 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即可。
1 2 3 4 5 6 7 8 9 10 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。
1 2 FROM gcr.io/google-samples/cassandra:v14ADD 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时会有依赖错误的情况。
1 2 3 4 5 6 7 8 9 10 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.7 ,apt-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
三,内置keyspaces 在容器构建时会执行run.sh脚本,因此我们在run.sh中插入一个sql文件并执行,即可完成keyspaces的构建。
在启动服务前异步执行一个initdb.sh的脚本,由于cql不能通过管道命令执行sql语句,只能通过文件执行,因此需要再写一个sql文件。
1 2 3 4 5 6 7 8 9 #!/bin/bash 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 FROM yourimageRUN rm -rf /etc/apt/sources.list && mkdir /root/.pip/ COPY sources.list /etc/apt/ COPY seaweedfs.sql /home COPY run.sh / COPY initdb.sh / RUN chmod 777 /run.sh \ && chmod 777 /initdb.sh \ && chmod 777 /home/seaweedfs.sql 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
将需要的文件拷贝其中并授权。
source.list:镜像源。这一步踩坑在于使用了阿里的镜像源后,apt-get install python2.7 会有依赖错误,具体原因未知。
使用apt-get update,这一步踩坑点在于apt-get update过程中会有不影响的错误,需在后面加入;exit 0来忽略错误。
使用-y参数时请在后面加上–allow-unauthenticated否则会报无权限错误。
上面三个RUN命令请不要合再一起写,否则会报错如下,意思是你使用的镜像源未被认证,当单独执行apt-get update 时在更新仓库时会自动注册上去。
之后成功build镜像,验证成功,内置了一个keyspaces
涉及命令 1 2 3 4 5 6 7 8 9 kubectl cp /root/cassandra.yaml firstrain/cassandra-0:/opt/cassandra.yaml docker inspect images docker build -t cassandra:v14-mine