卸载 k8s集群


1、平滑移除 Node

kubectl get node
kubectl cordon $node_name # 不可调度
kubectl drain $node_name # 驱逐资源
kubectl delete $node_name
kubectl drain k8s-node1 --delete-local-data --force --ignore-daemonsets

kubectl delete node --all

for service in kube-apiserver kube-controller-manager kubectl kubelet kube-proxy kube-scheduler; 
do
      systemctl stop $service
done

sudo kubeadm reset -f

# 合并版
sudo rm -rf $HOME/.kube && rm -rf ~/.kube/ && rm -rf /etc/kubernetes/ && rm -rf /etc/systemd/system/kubelet.service.d && rm -rf /etc/systemd/system/kubelet.service && rm -rf /usr/bin/kube* && rm -rf /etc/cni && rm -rf /opt/cni && rm -rf /var/lib/etcd && rm -rf /var/etcd

# 分步骤版
sudo rm -rf $HOME/.kube 
sudo rm -rf ~/.kube/
sudo rm -rf /etc/kubernetes/
sudo rm -rf /etc/systemd/system/kubelet.service.d
sudo rm -rf /etc/systemd/system/kubelet.service
sudo rm -rf /usr/bin/kube*
sudo rm -rf /etc/cni
sudo rm -rf /opt/cni
sudo rm -rf /var/lib/etcd
sudo rm -rf /var/etcd


yum clean all
yum remove kube*

docker images
docker rmi 

# 清空所有容器和镜像

docker rm -f $(docker ps -a -q)
docker images

docker rmi $(docker images | grep "^<none>" | awk "{print $3}")  # 删除没标签的镜像

docker rmi $(docker images -q)  # 删除全部镜像

安装k8s集群 (后期换成 ansible的方式安装)

世纪机房:

168、169、170、171、172、173、174、175、(176-181是mysql)182、183、184、185、186、187、188、189、190、197、198

85、86、87、88、89、90、91、92、93、94

1、时间同步

yum install -y chrony && systemctl enable --now chronyd

2、设置主机名

hostnamectl set-hostname k8s-173
echo "192.168.10.203   $(hostname)" >> /etc/hosts

3、关防火墙、禁用交换内存、关selinux

systemctl status firewalld.service 
systemctl stop firewalld.service
systemctl disable firewalld.service

swapoff -a
sed -i 's/.*swap.*/#&/' /etc/fstab
# sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
free -h

sestatus 
setenforce 0
sed -i "s/^SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
# sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

sestatus 

reboot
# 需要重启生效

4、配置网络

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system

# 开放端口 6443 2379-2380 10250 10251 10252 30000-32767

# 查看网卡配置是否正确,否则修改配置并重启网卡使生效
cat /etc/sysconfig/network-scripts/ifcfg-enp0s3

5、安装docker

yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum -y update
yum list docker-ce --showduplicates | sort -r
yum install -y docker-ce docker-ce-cli containerd.io
docker version
mkdir -p /etc/docker

cat <<EOF | sudo tee /etc/docker/daemon.json
{
    "registry-mirrors": ["https://xxx.mirror.aliyuncs.com"],
	"insecure-registries": ["harbor_ip:port"],
	"exec-opts": ["native.cgroupdriver=systemd"],
	"storage-driver": "overlay2",
    "storage-opts": [
    "overlay2.override_kernel_check=true"
  ],
	"log-driver": "json-file",
	"log-opts": {
		"max-size": "10m",
		"max-file": "1"
	}
}
EOF


vim /lib/systemd/system/docker.service

# 第14行,修改
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --default-ulimit core=0:0

systemctl daemon-reload
systemctl restart docker
systemctl status docker
systemctl enable docker

docker info
systemctl status docker -l

# 如果启动失败
systemctl status docker.service
journalctl -xe

6、配置k8s源 并安装 kubectl、kubelet、kubeadm

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

yum install -y kubectl kubelet kubeadm

kubelet --version
kubeadm version
kubectl version --client

systemctl enable kubelet && systemctl start kubelet

7、初始化 master

# 查看初始化所需镜像
kubeadm config images list
# 或者
kubeadm config images list --kubernetes-version=v1.21.3


kubeadm init --kubernetes-version=1.21.3  \
--apiserver-advertise-address=192.168.1.24   \
--image-repository registry.aliyuncs.com/google_containers  \
--pod-network-cidr=172.16.0.0/16

# 最新一次
kubeadm init --kubernetes-version=1.22.4  \
--apiserver-advertise-address=192.168.10.147   \
--image-repository registry.aliyuncs.com/google_containers  \
--pod-network-cidr=172.16.0.0/16

# 报错
error execution phase preflight: [preflight] Some fatal errors occurred:
	[ERROR ImagePull]: failed to pull image registry.aliyuncs.com/google_containers/coredns:v1.8.0: output: Error response from daemon: manifest for registry.aliyuncs.com/google_containers/coredns:v1.8.0 not found: manifest unknown: manifest unknown
, error: exit status 1

# 修复方案
kubeadm config images list

k8s.gcr.io/kube-apiserver:v1.21.3
k8s.gcr.io/kube-controller-manager:v1.21.3
k8s.gcr.io/kube-scheduler:v1.21.3
k8s.gcr.io/kube-proxy:v1.21.3
k8s.gcr.io/pause:3.4.1
k8s.gcr.io/etcd:3.4.13-0
k8s.gcr.io/coredns/coredns:v1.8.0

docker pull coredns/coredns

docker tag coredns/coredns:latest registry.aliyuncs.com/google_containers/coredns:v1.8.0

# 再次

kubeadm init --kubernetes-version=1.21.3  \
--apiserver-advertise-address=192.168.1.24   \
--image-repository registry.aliyuncs.com/google_containers  \
--pod-network-cidr=172.16.0.0/16

# 此时执行
1、生成 apiserver-kubelet-client、proxy、etcd 等的证数 和 密钥;
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [k8s-24 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.1.24]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [k8s-24 localhost] and IPs [192.168.1.24 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [k8s-24 localhost] and IPs [192.168.1.24 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key

2、往/etc/kubernetes 写入各个配置文件
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file

3、kubelet 配置环境变量与配文件,并启动
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet

4、为 kube-apiserver、kube-controller-manager 、 kube-scheduler和etcd创建静态pods
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in 

5、启动 control plane 完成,存储 kubeadm配置到 kube-system 命名空间
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 14.503785 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.21" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node k8s-24 as control-plane by adding the labels: [node-role.kubernetes.io/master(deprecated) node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[mark-control-plane] Marking the node k8s-24 as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]

6、引导令牌
[bootstrap-token] Using token: 123456
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
7、应用基本插件 CoreDNS 和 kube-proxy
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

8、配置文件、部署网络pod、其他节点加入;
root用户直接执行 export KUBECONFIG=/etc/kubernetes/admin.conf

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.1.24:6443 --token 123456 \
	--discovery-token-ca-cert-hash sha256:123456


mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

8、加入Node

# 查看现有 token
kubeadm token list 
# token 过期(24h)的话,重新生成 token
kubeadm token create 

# 查看 discovery-token-ca-cert-hash
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \
   openssl dgst -sha256 -hex | sed 's/^.* //'

kubeadm join 192.168.1.24:6443 --token 123 --discovery-token-ca-cert-hash sha256:123

# 执行一系列检查后,启动kubelet,并显示 node 已成功加入集群
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
kubectl get nodes -o wide # 可以看到29台机器的信息,其中master机器的 roles 是 control-plane,master
kubectl get pods -o wide --all-namespaces # 可以看到当前的所有pod的信息以及分布的IP,每台work都有 kube-proxy,master上有 etcd、kube-apiserver、kube-controller-manager、kube-scheduler、kube-proxy、coredns,且这些pod都属于kube-system的命名空间

9、安装网络pod

nodes是 not ready 的状态,且 coredns 的 pod 是没有 ready 的状态,需要安装网络插件

172.16.0.0/16 是指32位IP的后16位是可变范围;

curl https://docs.projectcalico.org/manifests/calico.yaml -O
vim calico.yaml

apiVersion: policy/v1  # policy/v1beta1 改为 policy/v1
kind: PodDisruptionBudget

- name: CALICO_IPV4POOL_CIDR
  value: "172.16.0.0/16"
# 保存

# 创建资源并应用配置
kubectl apply -f calico.yaml

# 查看 node 是否 ready,corndns 是否ready
watch kubectl get pods -n calico-system

10、其他

kubectl 命令自动补全

yum install bash-completion -y
source /usr/share/bash-completion/bash_completion
source <(kubectl completion bash)

pod


部署 pod

1、创建一个 Demo 项目:

DevOpsLab/K8sLab/k8s_demo.py

import datetime
import time

while 1:
    print(str(datetime.datetime.now())[:19])
    time.sleep(5)

2、创建dockerfile

DevOpsLab/dockerfile

FROM harbor_ip:port/copyright_monitor/python:3.8
COPY ./ /usr/DevOpsLab/
WORKDIR /usr/DevOpsLab/K8sLab

3、制作一个镜像,并上传到 harbor

docker build -t k8s-lab .
docker tag k8s-lab harbor_ip:port/copyright_monitor/k8s-lab
docker push harbor_ip:port/copyright_monitor/k8s-lab

4、创建 secret

kubectl create secret docker-registry harbor-root --namespace=default  \
--docker-server=harbor_ip:port \
--docker-username=root \
--docker-password='123'

5、编写 pod 资源配置文件

资源名称不能带下划线

vim k8s_pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: k8s-lab
spec:
  containers:
    - name: k8s-lab
      image: harbor_ip:port/copyright_monitor/k8s-lab
      imagePullPolicy: Always
      command: ["python","-u","k8s_demo.py"]
  imagePullSecrets:
  - name: harbor-root

kubectl apply -f k8s_pod.yaml

查看pod

# 如果READY 一直是 0/1 ,STATUS 是 CrashLoopBackOff,此时需要
kubectl describe pod k8s-lab -n kube-system
kubectl logs -f k8s-lab


# 查看pod在哪个节点运行
kubectl get pod -o wide
# 然后登录那台机器,通过 docker ps 和 docker images 可以看到该容器以及所需的镜像
# 容器的名称是 k8s_k8s-lab_k8s-lab_default_684751c4-c
# k8s_{containerName}_{podFullName}_{namespace}_{podUID}_{podrestartCount}

# 进入 pod
kubectl exec -it podname -c container_name -- bin/sh

至此,一个pod部署完成。

pod 参数

apiVersion: v1                    #必选,版本号,例如v1,版本号必须可以用 kubectl api-versions 查询到 .
kind: Pod                      #必选,Pod
metadata:                      #必选,元数据
  name: string                    #必选,Pod名称
  namespace: string               #必选,Pod所属的命名空间,默认为"default"
  labels:                       #自定义标签
    - name: string                 #自定义标签名字
  annotations:                           #自定义注释列表
    - name: string
spec:                            #必选,Pod中容器的详细定义
  containers:                       #必选,Pod中容器列表
  - name: string                        #必选,容器名称,需符合RFC 1035规范
    image: string                       #必选,容器的镜像名称
    imagePullPolicy: [ Always|Never|IfNotPresent ]  #获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,否则下载镜像,Nerver表示仅使用本地镜像
    command: [string]               #容器的启动命令列表,如不指定,使用打包时使用的启动命令
    args: [string]                     #容器的启动命令参数列表
    workingDir: string                     #容器的工作目录
    volumeMounts:                 #挂载到容器内部的存储卷配置
    - name: string                 #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
      mountPath: string                 #存储卷在容器内mount的绝对路径,应少于512字符
      readOnly: boolean                 #是否为只读模式
    ports:                      #需要暴露的端口库号列表
    - name: string                 #端口的名称
      containerPort: int                #容器需要监听的端口号
      hostPort: int                    #容器所在主机需要监听的端口号,默认与Container相同
      protocol: string                  #端口协议,支持TCP和UDP,默认TCP
    env:                          #容器运行前需设置的环境变量列表
    - name: string                    #环境变量名称
      value: string                   #环境变量的值
    resources:                          #资源限制和请求的设置
      limits:                       #资源限制的设置
        cpu: string                   #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
        memory: string                  #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
      requests:                         #资源请求的设置
        cpu: string                   #Cpu请求,容器启动的初始可用数量
        memory: string                    #内存请求,容器启动的初始可用数量
    livenessProbe:                    #对Pod内各容器健康检查的设置,当探测无响应几次后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法即可
      exec:                     #对Pod容器内检查方式设置为exec方式
        command: [string]               #exec方式需要制定的命令或脚本
      httpGet:                    #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
        path: string
        port: number
        host: string
        scheme: string
        HttpHeaders:
        - name: string
          value: string
      tcpSocket:            #对Pod内个容器健康检查方式设置为tcpSocket方式
         port: number
       initialDelaySeconds: 0       #容器启动完成后首次探测的时间,单位为秒
       timeoutSeconds: 0          #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
       periodSeconds: 0           #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
       successThreshold: 0
       failureThreshold: 0
       securityContext:
         privileged: false
    restartPolicy: [Always | Never | OnFailure] #Pod的重启策略,Always表示一旦不管以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示不再重启该Pod
    nodeSelector: obeject         #设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定
    imagePullSecrets:         #Pull镜像时使用的secret名称,以key:secretkey格式指定
    - name: string
    hostNetwork: false            #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
    volumes:                  #在该pod上定义共享存储卷列表
    - name: string              #共享存储卷名称 (volumes类型有很多种)
      emptyDir: {}              #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
      hostPath: string            #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
        path: string                #Pod所在宿主机的目录,将被用于同期中mount的目录
      secret:                 #类型为secret的存储卷,挂载集群与定义的secre对象到容器内部
        scretname: string  
        items:     
        - key: string
          path: string
      configMap:                      #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
        name: string
        items:
        - key: string
          path: string

1、基础参数(必选)

apiVersion: v1 # API版本号,不同的对象可能会使用不同API
kind: Pod  # 对象类型,pod
metadata:  # 元数据
  name: string # POD名称
  namespace: string # 所属的命名空间
spec: # specification of the resource content(资源内容的规范)
  containers: # 容器列表
    - name: string # 容器名称
      image: string # 容器镜像

2、标签与注释

metadata:
   labels: 
     - key: value 
     - ...
    annotations: 
      - key: value 
      - ...

3、容器常用参数

spec:
  containers:
    - name: string # 容器名称
# 镜像
      image: string
      imagePullPolicy: [Always| Never | IfNotPresent] 
      # 镜像拉取策略。Always:总是拉取;Never:从不拉取;IfNotPresent:不存在就拉取
# 启动参数
      command: [string] 
      # 容器启动命令列表,相当于Dockerfile中的ENDRYPOINT,是唯一的。如果不指定,就是使用容器本身的。示例:["/bin/sh","-c"]
      args: [string] 
      # 容器启动参数列表,相当于Dockerfile中的CMD,示例:["-c"]
# 容器工作目录
      workingDir: string
# 环境变量
      env:
        - name: string # 变量名称
          value: * # 变量值
        - name: string 
          valueFrome: # 指定值的来源
            configMapkeyRef: # 从ConfigMap中获取
              name: string # 指定ConfigMap
              key: string # 指定configMap中的key,赋值给变量
# 端口  
      ports: # 需要暴露的端口列表
        - name: string # 端口名称
          containerPort: int  # 容器端口
          hostPort: int # 容器所在主机需要监听的端口号,默认为与容器IP相同,一般可以不设置
          protocol: string # 端口协议,支持TCP和UDP,默认为TCP
# 挂载          
      volumeMounts: # 挂载定义的存储卷到容器,需要通过volumes定义
        - name: string # 定义的volume的名称
          mountPath: string # 容器内挂载的目录的绝对路径(少于512字符)
          readOnly: boolean(布尔值) # 是否只读

4、资源配额

cpu 超过 limits,pod会被限制,内存超过 limits,pod会被kill;
requests 默认和 limits 相等;

resource:
  limits: # 资源限制
    cpu: string # CPU限制。两种方式可以直接指定使用核数,也可以用单位:m来指定。 
	            # 0.5 :相当于0.5颗
	            # 一台服务器的CPU总量等于核数乘以1000。设机器的核数为两核,则总量为2000m。此时设置CPU限制为100m,则相当于是使用了100/2000,也就是5%。此时0.5=500m
    memory: string # 内存限制。
	               # 单位:直接使用正整数表示Byte;k;m;g;t;p
	               # 不区分大小写(Kilobyte,Megabyte,Gigabyte,Terabyte,Petabyte)
    requests:  # 资源请求设置,也就是容器启动时的初始资源请求,一般和limits相同可不设
      cpu: string
      memory: string

5、存储卷

可以定义 临时存储卷、持久存储卷、宿主机目录、配置文件、secret,从而给容器内部用。

spec:
  volumes: # 存储卷有多种类型,以下为一些常用类型
    - name: string # 存储卷名称
      emptyDir: {} # 该类存储卷是临时生成的一个目录,与pod生命周期同步
    - name: string 
      hostPath: # 挂载宿主机的目录
        path: string   # 用于挂载的目录
    - name: string
      nfs:
        server: string # 服务IP地址
        path: string # 用于挂载的目录
    - name: string
      persistentVolumeClaim: # 调用已经创建的持久卷
            claimName: string # 持久卷声明的名称
    - name: string
      configMap: # 挂载ConfigMap到容器内
        name: string # ConfigMap的名称
        items: # 要调用的键,值会被写入文件,可以设定多个,在被volumeMounts调用时,这些文件会被一起放在挂载目录下,也可以挂入到一个文件
          - key: string
            path: string  # 文件名
    - name: string
      secret: # 挂载secret到容器内
        secretname: string
        items:
          - key: string
            path: string

调用存储定义

spec:
  containers:
  ....
    volumeMounts:
       - name: main-conf
         mountPath: /etc/nginx/nginx.conf
         subPath: nginx.conf

6、健康检查

livenessProbe: # 如果探测失败会重启容器
   exec: # 通过在容器内执行命令或脚本的方式,命令执行状态码为0,视为探测成功
     command: [string]
   httpGet: # 通过http get的方式访问容器IP地址,并指定端口和路径,如果响应码会2xx或3xx视为成功
     path: string # 访问路径,也就是UPI示例:/index.html
     port: number # 访问端口
     host: string # 访问的主机名,默认为容器IP,可不设
     scheme: string # 用于连接的协议,默认为http,可不设
     httpHeaders: # 自定义请求头
       - name: string # 名称
         value: string # 值
   tcpSocket: # 通过tcp协议对端口进行检测如果端口可以连通就视为检测成功
     port: number
# 检测参数配置
    initialDelaySeconds: number # 初始延迟秒数,也就容器启动多久后开始检测
    timeoutSeconds: number # 响应超时时间
    periodSeconds: number # 检测周期,也就检测时间间隔

7、其他

spec:
  restartPolicy: [Always|Never|OnFailure] # 重启策略                       # OnFailure:只有在pod为非0码退出时才重启
  nodeSelector: # 根据标签调度到的指定node节点,使用前需要对节点打标签
     key: value # 使用命令kubectl label nodes node-name key=value 
   imagePullSecrets: # 指定镜像拉取时使用账户密码。需要先保存到Secret中
      - name: string
   hostNetwork: false # 是否使用主机网络,默认为false

pod 可配置:https://zhuanlan.zhihu.com/p/108018157

k8s科普:

面板:kuboard dashboard lens

面板


dashboard

0、如果之前存在,则删除旧的 dashboard

kubectl -n kubernetes-dashboard  delete $(kubectl -n kubernetes-dashboard  get pod -o name | grep dashboard)
# 或者
kubectl delete -f recommended.yaml

1、下载 dashboard 资源文件

查看 k8s 和 dashboard 版本对应 https://github.com/kubernetes/dashboard/releases

mkdir -p /usr/k8s_yaml/dashboard

wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.3.1/aio/deploy/recommended.yaml

或许会报错:
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|0.0.0.0|:443… failed: Connection refused.

需要在 https://www;.ipaddress.com/ 中查询 raw.githubuercontent.com 的真实IP,然后加入 hosts,在重新执行 wget 命令。

vim /etc/hosts

185.199.108.133 raw.githubusercontent.com
185.199.109.133 raw.githubusercontent.com
185.199.110.133 raw.githubusercontent.com
185.199.111.133 raw.githubusercontent.com

2、解析资源文件

打开 recommended.yaml,可以看到做了如下配置

一个 名为 kubernetes-dashboard 的 Namespace;

其余资源都在 这个 Namespace下配置;

一个 名为 kubernetes-dashboard 的 ServiceAccount;
一个 名为 kubernetes-dashboard 的 Service;
一个名为 kubernetes-dashboard-certs 的 Secret;
一个名为 kubernetes-dashboard-csrf 的 Secret;
一个名为 kubernetes-dashboard-key-holder 的 Secret;
一个名为 kubernetes-dashboard-settings 的 ConfigMap;
一个名为 kubernetes-dashboard 的 Role;
一个名为 kubernetes-dashboard 的 ClusterRole;
一个名为 kubernetes-dashboard 的 RoleBinding;
一个名为 kubernetes-dashboard 的 ClusterRoleBinding;
一个名为 kubernetes-dashboard 的 Service;
一个名为 dashboard-metrics-scraper 的 Deployment;

3、修改资源文件

修改对外端口

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  type: NodePort #增加
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 30000  # 增加,对外端口为30000
  selector:
    k8s-app: kubernetes-dashboard

修改 token过期时间

args:
            - --auto-generate-certificates
            - --namespace=kubernetes-dashboard
            - --token-ttl=43200  # 增加,修改为 token失效时间12小时

4、配置证书(不用执行)

mkdir dashboard-certs

cd dashboard-certs/

openssl genrsa -out dashboard.key 2048

openssl req -new -out dashboard.csr -key dashboard.key -subj '/CN=dashboard-cert'

openssl x509 -req -in dashboard.csr -signkey dashboard.key -out dashboard.crt -days 36500

kubectl create secret generic kubernetes-dashboard-certs --from-file=dashboard.key --from-file=dashboard.crt -n kubernetes-dashboard

5、创建

kubectl create -f recommended.yaml

# 此时报错 The connection to the server localhost:8080 was refused - did you specify the right host or port?

# 解决:
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> /etc/profile
source /etc/profile

#再次创建,并查看部署情况:
kubectl create -f recommended.yaml
kubectl get pods --all-namespaces
kubectl get pods -A  -o wide
kubectl get service -n kubernetes-dashboard  -o wide
kubectl get pod,svc -n kubernetes-dashboard # dashboard 关联 pod 和 service 的状态
kubectl describe pod podname -n kubernetes-dashboard

6、创建dashboard管理员

vim dashboard-admin.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: dashboard-admin
  namespace: kubernetes-dashboard

kubectl create -f dashboard-admin.yaml

7、分配权限

vim dashboard-admin-bind-cluster-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: dashboard-admin-bind-cluster-role
  labels:
    k8s-app: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: dashboard-admin
  namespace: kubernetes-dashboard

kubectl create -f dashboard-admin-bind-cluster-role.yaml

8、查看 token

kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep dashboard-admin | awk '{print $1}')

9、访问 dashboard

输入 https://ip:NodePort
输入 token

kuboard

参考:https://www.kuboard.cn/install/v3/install-in-k8s.html#%E5%AE%89%E8%A3%85
1、安装

kubectl apply -f https://addons.kuboard.cn/kuboard/kuboard-v3.yaml
watch kubectl get pods -n kuboard

访问 http://your-node-ip-address:30080

2、重置admin账户密码

kubectl exec -it -n kuboard $(kubectl get pods -n kuboard | grep kuboard-v3 | awk '{print $1}') -- /bin/bash

kuboard-admin reset-password

3、卸载

kubectl delete -f https://addons.kuboard.cn/kuboard/kuboard-v3.yaml
rm -rf /usr/share/kuboard

lens

kubeconfig里是内网IP 怎么导入lens呀

把apiserver用ssl转发出去,随便做个nginx做个四层转发就OK了,nginx对外

把项目拆分为多个模块,部署到k8s


应用分类

我们目前的业务中运行的业务可以分为如下:

1、脚本程序:特点是只需要部署一份,且更改相对频繁,需要实时看到运行状态,比如:调度程序、统计程序、监控程序等;

2、需要部署多个的服务:特点是需要多机部署,比如爬虫、数据分析、提特征、抽帧等;

3、HTTP 接口:特点是需要提供给内部或者外部调用,比如系统、服务类接口等;

需要部署多个的服务使用k8s会得到最直观的优化,比如部署、扩容缩容、实时监控等都非常方便,因此,先用一个分布式部署的服务,获取视频信息服务做实验。

部署 Deployment(VideoComplete)

1、项目描述

VideoComplete 是一个scrapy-redis项目,用来补充视频信息;

2、编写 项目依赖的 python 包

新建文件夹 video-complete ,把项目 VideoComplete 放入 video-complete;
在 video-complete/VideoComplete 路径 下 新建 requirements.txt 文件,并编辑

scrapy==2.5.0
redis==3.5.3
scrapy_redis==0.7.1
kafka-python==2.0.2
beautifulsoup4

3、制作镜像

在 video-complete路径 下 新建 dockerfile 文件,并编辑

FROM harbor_ip:port/copyright_monitor/python:3.8
COPY ./ /usr/VideoComplete/
RUN pip install --no-cache-dir -r requirements.txt -i  https://pypi.tuna.tsinghua.edu.cn/simple/
WORKDIR /usr/VideoComplete/VideoComplete

4、构建镜像并上传到私有镜像仓库 harbor

在 video-complete 路径 下 新建 build_and_push_image.sh

#!/bin/bash -ilex

echo "Start build image..."
# shellcheck disable=SC2164

docker build -t video-complete .

echo "Build  image successful!"

echo "Start push image..."

docker tag video-complete harbor_ip:port/copyright_monitor/video-complete

docker push harbor_ip:port/copyright_monitor/video-complete

echo "Push image successful!"

5、放到服务器上,执行构建与上传镜像脚本

yum install dos2unix

dos2unix build_and_push_image.sh

bash build_and_push_image.sh

6、编写 yaml 文件,在 k8s 上部署 deployment

参考

deployment 功能:

  • 定义一组Pod期望数量,Controller会维持Pod数量与期望数量一致
  • 配置Pod的发布方式,controller会按照给定的策略更新Pod,保证更新过程中不可用Pod维持在限定数量范围内
  • 发布有问题支持回滚

deployment 原理:

  • 实际状态与期望状态不断比较,有偏差则调整
  • 实际状态:Kubelet通过心跳汇报的容器和节点状态、监控系统中的监测数据、控制器主动收集的数据;
    期望状态:用户提交的 yaml 文件,保存在 etcd 中;
  • 控制器从etcd中根据标签等参数获取实际pod的数量,并与 yaml 定义的 replicas(期望值)比较,来决定删除还是创建 pod;

如何部署到指定的 node:

方法1 node Selector:

  • 通过 kubectl get node --show-labels 查看每个node 的label(有多个等号 连接的键值对,用逗号分隔)
  • 可以通过 kubectl label node-name key=value 来给指定node打标签,也可以不打,用系统默认的标签
  • 通过 nodeSelector(在yaml中和containers平级) 指定 label,从而部署到指定 node
  • ps:只能指定一个node,多个的话需要用到方法2的节点亲和性

方法2 节点亲和性:

可以分配到指定的多个node

参考:https://kubernetes.io/zh/docs/concepts/scheduling-eviction/assign-pod-node/

分为

硬要求(requiredDuringSchedulingIgnoredDuringExecution )和
软要求(preferredDuringSchedulingIgnoredDuringExecution)

spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - k8s-11
            - k8s-12
            - k8s-13

如果我们要在不同的3个机器部署3个副本,即 replicas 是 3,如果按照上面的写法,只能保证部署范围是这三个节点,但是不能保证部署的3个副本在3个不同的节点,因为会有一个节点部署两个副本而另一个节点没副本的情况,此时需要用到pod反亲和性:

spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
              - key: app
                operator: In
                values:
                  - video-complete
          topologyKey: "kubernetes.io/hostname"
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - k8s-11
            - k8s-12
            - k8s-13

方法3:yaml 中指定 nodeName (和 containers 平级)

定义 deployment.yaml

template 前是控制器的定义,template里的pod的定义;

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-video-complete
spec:
  restartPolicy: Always
  replicas: 3
  selector:
    matchLabels:
      app: video-complete
  template:
    metadata:
      labels:
        app: video-complete
    spec:
      containers:
        - name: video-complete-74
          image: harbor_ip:port/copyright_monitor/video-complete
          imagePullPolicy: Always
          command: ["python","-u","start_0.74.py"]
        - name: video-complete-73
          image: harbor_ip:port/copyright_monitor/video-complete
          imagePullPolicy: Always
          command: [ "python","-u","start_0.73.py" ]
        - name: video-complete-72
          image: harbor_ip:port/copyright_monitor/video-complete
          imagePullPolicy: Always
          command: [ "python","-u","start_0.72.py" ]
        - name: video-complete-71
          image: harbor_ip:port/copyright_monitor/video-complete
          imagePullPolicy: Always
          command: [ "python","-u","start_0.71.py" ]
        - name: video-complete-7
          image: harbor_ip:port/copyright_monitor/video-complete
          imagePullPolicy: Always
          command: [ "python","-u","start_0.7.py" ]
      imagePullSecrets:
      - name: harbor-root
      affinity:
        podAntiAffinity:
	      requiredDuringSchedulingIgnoredDuringExecution:
	        - labelSelector:
	            matchExpressions:
	              - key: app
	                operator: In
	                values:
	                  - video-complete
	          topologyKey: "kubernetes.io/hostname"
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: kubernetes.io/hostname
                    operator: In
                    values:
                      - k8s-11
                      - k8s-12
                      - k8s-13

这样就保证了3个副本限制在3个node运行,且不同副本不能在同一node运行;

创建 deployment

kubectl apply -f deployment.yaml
kubectl get deployments
kubectl get pods -o wide --show-labels  --all-namespaces
kubectl get pods -l app=video-complete --show-labels
kubectl delete deployments nginx-deployment
kubectl delete -f deployment.yaml
kubectl describe deployment deployment-video-complete

kubectl get deployment 发现 READY 是 2/3 ,即有一个pod失败了,再通过
kubectl get pods -o wide --all-namespaces发现是k8s-11的 deployment-video-complete-56fb54df4d-nm2ds READY 是0/5,然后kubectl describe pod deployment-video-complete-56fb54df4d-nm2ds发现

Failed to create pod sandbox: rpc error: code = Unknown desc = failed to start sandbox container for pod "deployment-video-complete-56fb54df4d-nm2ds": operation timeout: context deadline exceeded

error determining status: rpc error: code = DeadlineExceeded desc = context deadline exceeded

通过 kubectl get pods -o wide --all-namespaces 查看,发现 k8s-11机器的 calico 的READY 状态是 0/1,最后我是通过卸载calico插件并重装解决的

kubectl delete -f calico.yaml
kubectl apply -f calico.yaml

然后再删掉 deployment重新apply,再查看发现部署成功。

kubectl delete -f deployment.yaml
kubectl apply -f deployment.yaml

部署 Deployment(scrapyd-spider)

1、项目描述

scrapyd-spider 是一个scrapyd 项目,作为业务的主要数据获取源,需要在每台机器部署一个 scrapyd服务;

2、编写 项目依赖的 python 包

新建文件夹scrapyd-spider ,把 ScrapydSpider 放到 scrapyd-spider 文件夹下;

在 scrapyd-spider/ScrapydSpider 路径 下 新建 requirements.txt 文件,并编辑

attrs==19.3.0
Automat==20.2.0
beautifulsoup4==4.8.2
certifi==2019.11.28
cffi==1.14.0
chardet==3.0.4
constantly==15.1.0
cryptography==2.8
cssselect==1.1.0
demjson==2.2.4
fastdtw==0.3.4
hyperlink==19.0.0
idna==2.9
incremental==17.5.0
kafka-python==2.0.1
lxml==4.5.0
numpy==1.18.2
parsel==1.5.2
Protego==0.1.16
pyasn1==0.4.8
pyasn1-modules==0.2.8
pycparser==2.20
PyDispatcher==2.0.5
PyHamcrest==2.0.2
pymongo==3.10.1
PyMySQL==0.9.3
pyOpenSSL==19.1.0
python-dateutil==2.8.1
queuelib==1.5.0
redis==3.4.1
requests==2.23.0
Scrapy==2.0.1
scrapy-redis==0.6.8
scrapyd==1.2.1
selenium==3.141.0
service-identity==18.1.0
six==1.14.0
soupsieve==2.0
Twisted==20.3.0
urllib3==1.25.8
w3lib==1.21.0
zope.interface==5.0.1
pillow
mq_http_sdk
elasticsearch
emoji
gne
pypinyin
pyexecjs
pycryptodome

3、制作镜像

在 scrapyd-spider 路径 下 新建 dockerfile 文件,并编辑

FROM harbor_ip:port/copyright_monitor/python:3.8

RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone

RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add -

RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'

RUN apt-get -y update && apt-get install -y google-chrome-stable && apt-get install -yqq unzip

RUN wget -O /tmp/chromedriver.zip http://chromedriver.storage.googleapis.com/`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip

RUN unzip /tmp/chromedriver.zip chromedriver -d /usr/local/bin/

ENV DISPLAY=:99

COPY ./ /usr/scrapyd-spider


RUN pip install --no-cache-dir -r /usr/scrapyd-spider/ScrapydSpider/requirements.txt -i  https://pypi.tuna.tsinghua.edu.cn/simple/

RUN cp  /usr/scrapyd-spider/ScrapydSpider/default_scrapyd.conf /usr/local/lib/python3.8/site-packages/scrapyd/default_scrapyd.conf

WORKDIR /usr/scrapyd-spider/ScrapydSpider/

4、在 scrapyd-spider 路径 下 新建 build_and_push_image.sh 文件,并编辑

#!/bin/bash -ilex

echo "Start build image..."
# shellcheck disable=SC2164

docker build -t scrapyd-spider .

echo "Build image successful!"

echo "Start push image..."

docker tag scrapyd-spider harbor_ip:port/copyright_monitor/scrapyd-spider

docker push harbor_ip:port/copyright_monitor/scrapyd-spider

echo "Push image successful!"

bash build_and_push_image.sh

5、执行脚本,构建与上传镜像

dos2unix build_and_push_image.sh

bash build_and_push_image.sh

6、编写 yaml 文件,在 k8s 上部署 deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-scrapyd-download-video
spec:
  replicas: 10
  selector:
    matchLabels:
      app: scrapyd-download-video
  template:
    metadata:
      labels:
        app: scrapyd-download-video
    spec:
      hostNetwork: true
      restartPolicy: Always
      containers:
        - name: scrapyd-download-video
          image: harbor_ip:port/copyright_monitor/scrapyd-download-video
          imagePullPolicy: Always
          command: ["scrapyd"]

      imagePullSecrets:
      - name: harbor-root
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: app
                    operator: In
                    values:
                      - scrapyd-download-video
              topologyKey: "kubernetes.io/hostname"

执行部署命令

kubectl apply -f deployment-scrapyd-download-video.yaml
kubectl get pods -o wide --all-namespaces

发现一个节点的 STATUS 一直是 ContainerCreating 的状态,再查看这个pod的状态:

kubectl describe pod deployment-scrapyd-download-video-6c847d4668-pbl7k

发现如下错误:

Failed to create pod sandbox: rpc error: code = Unknown desc = failed to start sandbox container for pod "deployment-scrapyd-download-video-6c847d4668-pbl7k": operation timeout: context deadline exceeded

error determining status: rpc error: code = DeadlineExceeded desc = context deadline exceeded

到该节点上执行 系统日志查询

journalctl -xe

发现错误:

stream copy error: reading from a closed fifo

没找到解决办法,把 deployment delete之后再apply,错误就消失了;

部署 API 服务

参考:https://blog.csdn.net/M2l0ZgSsVc7r69eFdTj/article/details/79988685?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_title~default-0.no_search_link&spm=1001.2101.3001.4242

hostNetwork、NodePort,LoadBalancer 和 Ingress

docker container prune

制作精简的python镜像

3个地方可以精简

pip3 install --no-cache-dir -r /tmp/requirements.txt -i https://mirrors.aliyun.com/pypi/simple/

RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        python3-qrcode \
        python3-renderpm \
        python3-psycopg2 \
        python3-babel \
        python3-jinja2 \
        python3-pip \
        python3-wheel \
    && pip3 install --no-cache-dir -r /tmp/requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ 
    && rm -rf /var/lib/apt/lists/*

apt-get autoremove -y
apt-get remove -y python3-pip

K8s CICD方案

gitlab CICD

argo

jenkins
jenkinsX

gogs

drone

Tekton

使用 gitlab CICD 实现 k8s CICD


k8s双机房的CICD方案

我们目前有两个机房,我的 k8s双机房的CICD方案说明如下:

机房1:40台机器,装有 k8s集群、gitlab、Prometheus,在机房1所在的机器安装并注册gitlab-runner;

机房2:15台机器,装有k8s集群(和机房1的k8s集群独立),在k8s-master所在的机器安装并注册gitlab-runner;

双机房的master 安装与注册 gitlab-runner

1、在需要安装 gitlab-runner 的机器上安装 git

yum remove git

vim /etc/yum.repos.d/wandisco-git.repo

[wandisco-git]

name=Wandisco GIT Repository

baseurl=http://opensource.wandisco.com/centos/7/git/$basearch/

enabled=1

gpgcheck=1

gpgkey=http://opensource.wandisco.com/RPM-GPG-KEY-WANdisco

# 保存

rpm --import http://opensource.wandisco.com/RPM-GPG-KEY-WANdisco

yum -y install git
yum update git
git --version
# git version 2.31.1

2、卸载旧的 gitlab-runner(如果有的话)

gitlab-runner stop
chkconfig gitlab-runner off
gitlab-runner uninstall

# 清理文件
rm -rf /etc/gitlab-runner
rm -rf /usr/local/bin/gitlab-runner
rm -rf /usr/bin/gitlab-runner
rm -rf /etc/sudoers.d/gitlab-runner

yum remove gitlab-runner

3、安装 gitlab-runner 并注册 (二进制方式)

https://docs.gitlab.com/runner/install/linux-manually.html

二进制安装

curl -LJO "https://gitlab-runner-downloads.s3.amazonaws.com/latest/rpm/gitlab-runner_amd64.rpm"

rpm -i gitlab-runner_amd64.rpm

注册

sudo gitlab-runner register
# 1、输入gitlab 地址,Menu => admin => 概览 => Runner 中可以查看
# 2、输入 注册 token,Menu => admin => 概览 => Runner 中可以查看
# 3、输入 description (gitlab-runner-shared)
# 4、输入 tag (gitlab-runner-shared)
# 5、选择一个 executor (shell)

4、将 gitlab-runner 加入 docker 用户组

查看 gitlab-runner 是否有权访问 docker

sudo -u gitlab-runner -H docker info

将 gitlab-runner 用户 加入 docker 用户组,并再次验证

sudo usermod -aG docker gitlab-runner

sudo -u gitlab-runner -H docker info

cat /etc/group

sudo chmod a+rw /var/run/docker.sock

5、设置gitlab-runner 所在服务器的 gitlab-runner 到其他服务器(多机房方案中的k8s-master所在服务器)免密登录

gitlab-runner 所在服务器:

ps aux|grep gitlab-runner

su gitlab-runner
ssh-keygen -t rsa
cd  /home/gitlab-runner/.ssh
ls
# 复制到本机的root下
cat /home/gitlab-runner/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys

# 复制到其他机器
ssh-copy-id -i ~/.ssh/id_rsa.pub -p port username@remote_ip

6、设置 gitlab-runner 为系统服务,并开机自启动

7、在 k8s master 的机器上执行 chmod 666 /etc/kubernetes/admin.conf

video-complete 项目的CICD

1、在 gitlab中新建项目 video-complete

2、打开本地项目文件夹 video-complete,在文件夹内执行

git init --initial-branch=main
git remote add origin git@gitlab_ip:Ezrealer/video-complete.git
git add .
git commit -m "Initial commit"
git push -u origin main

3、刷新 gitlab,发现项目已提交成功

4、在本地项目文件夹的根目录创建 .gitlab-ci.yml 文件,并编辑

更新 k8s deployment的方法:

  • kubectl apply -f deployment.yaml (yaml文件需要有变化)
  • kubectl delete -f deployment.yaml && kubectl apply -f deployment.yaml (任何更新都会生效)
  • kubectl rollout restart deployment deployment-video-complete (只针对镜像更新生效,imagePullPolicy: Always)
  • kubectl scale deployment XXXX --replicas=0 -n {namespace} && kubectl scale deployment XXXX --replicas=1 -n {namespace} (只针对镜像更新生效,imagePullPolicy: Always)
  • kubectl set image deployment/nginx nginx=nginx:1.16.1 --record (只针对镜像更新生效)
  • 通过 kubectl patch deployment 更新
kubectl patch deployment <deployment-name> \
  -p '{"spec":{"template":{"spec":{"containers":[{"name":"<container-name>","env":[{"name":"RESTART_","value":"'$(date +%s)'"}]}]}}}}'
variables:
  IMAGE_NAME: "${HARBOR_REPOSITORY}/copyright_monitor/video-complete:${CI_COMMIT_SHORT_SHA}"
stages:
  - build
  - deploy

build-and-push-image:
  stage: build
  script:
    - pwd
    - ls
    - echo ${IMAGE_NAME}
    - echo $HARBOR_PASSWORD | docker login -u $HARBOR_USERNAME --password-stdin $HARBOR_REPOSITORY
    - docker build -t ${IMAGE_NAME} .
    # - docker tag video-complete ${IMAGE_TAG_NAME}
    - docker push ${IMAGE_NAME}
    - sleep 5

  tags:
    - century-computer-room

deploy-to-k8s:
  stage: deploy
  script:
    - pwd
    - ls
    - echo ${IMAGE_NAME}
    - envsubst < deployment-video-complete.yaml | kubectl apply -f -
  tags:
    - ruide-computer-room

5、把gitllab-ci.yml 的变量传递到 deployment.yaml

更多CICD 技巧

镜像与容器相关



制作镜像的步骤

第一基础镜像,是基于哪个操作系统,比如Centos7或者其他的

第二步中间件镜像,比如服务镜像,跑的像nginx服务,tomcat服务

第三步项目镜像,它是服务镜像之上的,将你的项目打包进去,那么这个项目就能在你这个服务镜像里面运行了

一般运维人员都是提前将镜像做好,而开发人员就能直接拿这个镜像去用,这个镜像一定要符合现在环境部署的环境

容器产生的三种数据

启动时需要的初始数据,比如配置文件;

启动过程中产生的临时数据,该临时数据可能需要多个容器间共享;

启动过程中产生的持久化数据;