感觉现在多数互联网公司就在朝着容器化的路上前行,大势所趋啊。之前陆续有过docker相关记录,管理方式也是docker-compose形式,其实对于一般小量级的docker-compose管理足以应付。但是如果追求更高些,kubernetes是绕不过去的。倘若docker不是太熟悉,可以参见之前的 docker 笔记一,docker 笔记二。
虽说不是专门负责基础运维,但是docker却是一直用,一直伴随各种问题,不断运用也能不断加深理解。本想花点时间再深入了解下内在机制和原理,奈何精力有限,只能把维护当中遇到的各个点记录下。
之前有过docker 笔记二有过镜像构建时候逐层叠加利用缓存的说明,在后续的 CI/CD中也有记录。那么在 Dockerfile 撰写时RUN
CMD
ENTRYPOINT
关键字有何值得注意的地方。
CMD有3种调用形式:
注意:
1,如果有多个CMD在dockerfile中,那么只有最后一个CMD命令有效。
2,如果docker run启动container时指定了CMD,则会覆盖镜像构建中指定的CMD
3,第二种形式的构建镜像Dockerfile中还需指定ENTRYPOINT
注意:
1,shell形式的使用方式会屏蔽任何的CMD。
2,如果需要执行多个指令,例如:先执行migrate,在启动服务,可以写入一个shell文件中,ENTRYPOINT执行该shell脚本即可。
在docker-compose中可以指定启动镜像时的CMD和ENTRYPOINT,形如:
version: '3.1'
services:
app:
image: your_django_image
#entrypoint: ./entrypoint.sh
command:
- gunicorn -w 4 -b 0.0.0.0:8000 your_wsgi -t 300 --log-level INFO
worker:
image: your_celery_image
command:
- celery
- -A
- ops
- worker
- -B
- -l
- info
extra_hosts:
- "your.host1.net:172.0.0.4"
- "your.host2.net:172.0.0.5"
此时如果app同时存在 entrypoint 和 command则会执行entrypoint,不会执行command。
在Dockerfile 中的所有关键字可以在官网介绍 查看。
在许多服务中,都会有修改本地/etc/hosts的需求,如果想通过 Dockerfile中 echo追加的形式,是不可行的,因为docker contaienr运行过程中会生成hosts,附加当前容器的id信息,构建镜像时echo追加内容都被冲掉。
正确做法可以在启动容器时添加 extra_hosts
参数,在上文中的docker-compose文件中的 extra_hosts
参数传入方式。
注意字符串格式必须是上面的
"host:ip"
格式
。
之前CI / CD笔记中有过挂在的操作记录。日前遇到一个问题,在Build镜像过程中,将某一路径下的文件 ADD 到镜像指定的一个 /container/test 路径下,之后再把 contaienr中的 /host/test 挂载到宿主机上。本意是想把启动后的 /container/test挂载到/host/test路径下方便查看内容。结果启动后,/container/test和/host/test都是空。
原因是挂在反了
。因为在构建镜像时文件已经ADD到镜像的指定路径下,启动容器后,宿主机上/host/test是空的,所以容器内的/container/test路径被置空。
对比数据库数据挂在到宿主机:
在容器启动mysql时经常挂载容器内的data卷/var/lib/mysql到host的/your_home/mysql_data路径下,把数据保留到本地。那是因为容器启动时宿主机和容器内的两个路径都是空的,容器mysql的服务,服务生成了数据文件在/var/lib/mysql,其生命周期是启动容器后,运行服务后服务生成的。
初窥门径,按照《Kubernetes权威指南》上的介绍,自己摸索着临时玩玩
,熟悉熟悉概念,组件功能,以及操作命令。
建议阅读下《Kubernetes权威指南》,如果有docker积累,阅读起来还是比较容易理解。
两台机器内网互通,选择 master节点 192.168.0.1,worker节点 192.168.0.2,系统环境CentOS 7.4,阿里云虚拟机。
在master节点上安装服务
yum install -y etcd docker kubernetes
systemctl start docker
# 修改hosts
echo 'kub-master 192.168.0.1' >> /etc/hosts
echo 'kub-node1 192.168.0.1' >> /etc/hosts
在master启动 kubernetes 服务之前先修改默认配置/etc/kubernetes。
apiserver 需要修改的配置项如下,其他默认即可
:
KUBE_API_ADDRESS="--address=0.0.0.0"
KUBE_MASTER="-–master=http://kub-master:8080"
config 需要修改的配置项如下,其他默认即可
:
KUBE_MASTER="--master=http://kub-master:8080"
kubelet 需要修改的配置项如下,其他默认即可
:
KUBELET_HOSTNAME="--hostname-override=kub-master"
KUBELET_API_SERVER="--api-servers=http://kub-master:8080"
依次启动服务:
systemctl start etcd
systemctl start kube-apiserver
systemctl start kube-controller-manager
systemctl start kube-scheduler
systemctl start kubelet
systemctl start kube-proxy
对应编写一个测试的RC文件mysql_rc.yml
用以启动Pod
apiVersion: v1
kind: ReplicationController
metadata:
name: mysql-test
spec:
replicas: 1
selector:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: root
- name: MYSQL_DATABASE
value: alexdb
- name: MYSQL_USER
value: alex
- name: MYSQL_PASSWORD
value: alex
ports:
- containerPort: 3306
hostPort: 33306
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumes:
- name: mysql-data
emptyDir: {}
此Pod直接指定了 hostPort 作为外部访问的端口,启动Pod
kubectl create -f mysql_rc.yml
kubectl get pods
在启动pod过程中,Pod的 status
一直在ContainerCreating
此时通过
kubectl describe pods your_pod_name
ailedSync Error syncing pod, skipping: failed to "StartContainer" for "POD" with ErrImagePull: "image pull failed for registry.access.redhat.com/rhel7/pod-infrastructure:latest, this may be because there are no credentials on this request. details: (open /etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt: no such file or directory)"
就是缺少证书,可以尝试
$ yum install *rhsm*
# 如果上面安装,文件并没有生成,可以再执行:
$ wget http://mirror.centos.org/centos/7/os/x86_64/Packages/python-rhsm-certificates-1.19.10-1.el7_4.x86_64.rpm
$ rpm2cpio python-rhsm-certificates-1.19.10-1.el7_4.x86_64.rpm | cpio -iv --to-stdout ./etc/rhsm/ca/redhat-uep.pem | tee /etc/rhsm/ca/redhat-uep.pem
再次尝试创建mysql Pod。
顺便说下,默认的mysql镜像是 mysql 8.0 的版本,用mysql 5.x的客户端连接会出异常:
ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded: /usr/lib64/mysql/plugin/caching_sha2_password.so: cannot open shared object file: No such fileor directory
在另一台woker机器上安装 docker kubernetes 修改hosts,并启动docker 服务。
config 需要修改的配置项如下,其他默认即可
:
KUBE_MASTER="--master=http://kub-master:8080"
kubelet 需要修改的配置项如下,其他默认即可
:
KUBELET_HOSTNAME="--hostname-override=kub-node1"
KUBELET_API_SERVER="--api-servers=http://kub-master:8080"
worker节点只需启动kubelet,kube-proxy服务:
systemctl start kubelet
systemctl start kube-proxy
同时在master节点上启动tomcat Pod集群,并指定servcie,对应的Pod启动的 tomcat_rc.yml 文件:
apiVersion: v1
kind: ReplicationController
metadata:
name: myweb
spec:
replicas: 5
selector:
app: myweb
template:
metadata:
labels:
app: myweb
spec:
containers:
- image: kubeguide/tomcat-app:v1
name: myweb
resources:
limits:
cpu: "2"
memory: 1Gi
ports:
- containerPort: 8080
env:
- name: MYSQL_SERVICE_HOST
value: 'mysql'
- name: MYSQL_SERVICE_PORT
value: '3306'
对应的tomcat-svc.yaml 内容如下:
apiVersion: v1
kind: Service
metadata:
name: myweb
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30007
selector:
app: myweb
启动对应的svc和rc
kubectl create -f tomcat-svc.yaml
kubectl create -f tomcat_rc.yml
再次在master
节点查看Pod
指定tomcat 5个Pod启动了2个,另外3个处于pending状态,是因为机器资源不够,只能启动2个Pod,同时在master和woker上查看docker。
master
节点docker 容器运行情况:
woker
节点容器运行情况:
可以看出tomcat的两个Pod是分别运行在master节点和woker几点两台机器上的。
1,证书问题
在woker几点注册到master节点通过 kubectl get nodes
可以查看时直接启动tomcat Pod会有问题,woker节点上也是没有证书。为了验证pod启动,直接类似mater申请了证书,这种做法能够让Pod后面正常启动,但是访问有问题。
2,在上面的处理方式下,woker几点调用kubectl
命令是会报出 The connection to the server localhost:8080 was refused - did you specify the right host or port?
。目前没有找到解决办法,初步估计也是证书。
3,woker节点上 kubectl
命令可以通过参数 -s
来执行api server如下:
kubectl -s kub-master:8080 get nodes
即可正常查看。
4,单节点启动tomcat,并启动对应的svc,再运行
curl 127.0.0.1:30007
是能够正常访问的,但是当集群启动时候就不能访问,会报出refuesd。
后续会尝试一个生产式的配置部署方式,这个纯粹因为看了《Kubernetes权威指南》临时熟悉。