运维笔记 -- docker、kubernetes

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/duxiangwushirenfei/article/details/82843318

前言

感觉现在多数互联网公司就在朝着容器化的路上前行,大势所趋啊。之前陆续有过docker相关记录,管理方式也是docker-compose形式,其实对于一般小量级的docker-compose管理足以应付。但是如果追求更高些,kubernetes是绕不过去的。倘若docker不是太熟悉,可以参见之前的 docker 笔记一docker 笔记二

docker -- tips

虽说不是专门负责基础运维,但是docker却是一直用,一直伴随各种问题,不断运用也能不断加深理解。本想花点时间再深入了解下内在机制和原理,奈何精力有限,只能把维护当中遇到的各个点记录下。

RUN CMD ENTRYPOINT

之前有过docker 笔记二有过镜像构建时候逐层叠加利用缓存的说明,在后续的 CI/CD中也有记录。那么在 Dockerfile 撰写时RUN CMD ENTRYPOINT关键字有何值得注意的地方。

RIN

  • RUN <command> 默认用的是 /bin/sh -c
  • RUN [“executable”, “param1”, “param2”]
    此二者都是在build镜像时需要调用命令构建中间层时使用,并非镜像启动服务使用。

CMD

CMD有3种调用形式:

  • CMD [“executable”,“param1”,“param2”] 可以执行文件或命令 + 参数param1,param2
  • CMD [“param1”,“param2”] 为ENTRYPOINT指定参数 param1和param2
  • CMD command param1 param2 以”/bin/sh -c”的方法执行的命令

注意:
1,如果有多个CMD在dockerfile中,那么只有最后一个CMD命令有效。
2,如果docker run启动container时指定了CMD,则会覆盖镜像构建中指定的CMD
3,第二种形式的构建镜像Dockerfile中还需指定ENTRYPOINT

ENTRYPOINT

  • ENTRYPOINT [“executable”, “param1”, “param2”]
  • ENTRYPOINT command param1 param2

注意:
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 中的所有关键字可以在官网介绍 查看。

hosts

在许多服务中,都会有修改本地/etc/hosts的需求,如果想通过 Dockerfile中 echo追加的形式,是不可行的,因为docker contaienr运行过程中会生成hosts,附加当前容器的id信息,构建镜像时echo追加内容都被冲掉。
正确做法可以在启动容器时添加 extra_hosts 参数,在上文中的docker-compose文件中的 extra_hosts 参数传入方式。
注意字符串格式必须是上面的 "host:ip" 格式

volume

之前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权威指南》上的介绍,自己摸索着临时玩玩,熟悉熟悉概念,组件功能,以及操作命令。
建议阅读下《Kubernetes权威指南》,如果有docker积累,阅读起来还是比较容易理解。
两台机器内网互通,选择 master节点 192.168.0.1,worker节点 192.168.0.2,系统环境CentOS 7.4,阿里云虚拟机。

master节点配置

在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 节点配置

在另一台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节点上查看node:
在这里插入图片描述

同时在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权威指南》临时熟悉。

猜你喜欢

转载自blog.csdn.net/duxiangwushirenfei/article/details/82843318