【DevOps】Centos 7.9 安装、部署与使用 k8s集群(v1.21.3)

2023-11-16

卸载 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科普:https://www.cnblogs.com/dukuan/p/11400344.html

面板: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

参考 https://blog.csdn.net/lixinkuan328/article/details/103993274

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

https://blog.csdn.net/kingwinstar/article/details/116976310

更多CICD 技巧

https://blog.csdn.net/weixin_36572983/article/details/86680515

镜像与容器相关


参考

https://www.cnblogs.com/wuchangblog/default.html

https://www.cnblogs.com/diantong/

制作镜像的步骤

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

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

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

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

容器产生的三种数据

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【DevOps】Centos 7.9 安装、部署与使用 k8s集群(v1.21.3) 的相关文章

  • 批量删除文件名中包含 BASH 中特殊字符的子字符串

    我的目录中有一个文件列表 opencv calib3d so2410 so opencv contrib so2410 so opencv core so2410 so opencv features2d so2410 so opencv
  • Linux 中 m 标志和 o 标志将存储在哪里

    我想知道最近收到的路由器通告的 m 标志和 o 标志的值 从内核源代码中我知道存储了 m 标志和 o 标志 Remember the managed otherconf flags from most recently received R
  • 有没有一种快速方法可以从 Jar/war 中删除文件,而无需提取 jar 并重新创建它?

    所以我需要从 jar war 文件中删除一个文件 我希望有类似 jar d myjar jar file I donot need txt 的内容 但现在我能看到从 Linux 命令行执行此操作的唯一方法 不使用 WinRAR Winzip
  • 如何使用 JSch 将多行命令输出存储到变量中

    所以 我有一段很好的代码 我很难理解 它允许我向我的服务器发送命令 并获得一行响应 该代码有效 但我想从服务器返回多行 主要类是 JSch jSch new JSch MyUserInfo ui new MyUserInfo String
  • 适用于 Linux 的轻量级 IDE [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何使用 Cloud Init 挂载未格式化的 EBS 卷

    Context 我正在使用https wiki jenkins io display JENKINS Amazon EC2 Plugin https wiki jenkins io display JENKINS Amazon EC2 Pl
  • 添加文件时运行 shell 命令

    我的 Linux 机器上有一个名为 images 的文件夹 该文件夹连接到一个网站 该网站的管理员可以向该网站添加图片 但是 当添加图片时 我想要一个命令来运行调整目录中所有图片的大小 简而言之 我想知道当新文件添加到特定位置时如何使服务器
  • 使用包管理器时如何管理 Perl 模块?

    A 最近的问题 https stackoverflow com questions 397817 unable to find perl modules in intrepid ibex ubuntu这让我开始思考 在我尝试过的大多数 Li
  • 配置tomat的server.xml文件并自动生成mod_jk.conf

    我在用apache 2 2 15 and tomcat6 6 0 24 on CentOS 6 4并希望使用 tomcat 服务器的功能 通过添加以下内容自动生成 mod jk conf 文件
  • Intel 上的 gcc 中的 _mm_pause 用法

    我参考过这个网页 https software intel com en us articles benefitting power and performance sleep loops https software intel com
  • 为什么opencv videowriter这么慢?

    你好 stackoverflow 社区 我有一个棘手的问题 我需要你的帮助来了解这里发生了什么 我的程序从视频采集卡 Blackmagic 捕获帧 到目前为止 它工作得很好 同时我用 opencv cv imshow 显示捕获的图像 它也工
  • 在生产服务器上使用 Subversion 使文件生效的最佳方法是什么?

    目前我已经设置了 subversion 这样当我在 Eclipse PDT 中进行更改时 我可以提交更改 它们将保存在 home administrator 中项目文件 该文件具有 subversion 推荐的 branches tags
  • 绕过 dev/urandom|random 进行测试

    我想编写一个功能测试用例 用已知的随机数值来测试程序 我已经在单元测试期间用模拟对其进行了测试 但我也希望用于功能测试 当然不是全部 最简单的方法是什么 dev urandom仅覆盖一个进程 有没有办法做类似的事情chroot对于单个文件并
  • 如何在 *nix 中登录时运行脚本?

    我知道我曾经知道如何做到这一点 但是 如何在 unix 中登录时运行脚本 bash 可以 From 维基百科 Bash http en wikipedia org wiki Bash 28Unix shell 29 当 Bash 启动时 它
  • Linux 为一组进程保留一个处理器(动态)

    有没有办法将处理器排除在正常调度之外 也就是说 使用sched setaffinity我可以指示线程应该在哪个处理器上运行 但我正在寻找相反的情况 也就是说 我想从正常调度中排除给定的处理器 以便只有已明确调度的进程才能在那里运行 我还知道
  • linux下如何从文本文件中获取值

    我有一些文本格式的文件 xxx conf 我在这个文件中有一些文本 disablelog 1 当我使用 grep r disablelog oscam conf 输出是 disablelog 1 但我只需要值1 请问你有什么想法吗 一种方法
  • 使用 gdb 调试 Linux 内核模块

    我想知道 API 在内核模块 中返回什么 从几种形式可以知道 这并不是那么简单 我们需要加载符号表来调试内核模块 所以我所做的就是 1 尝试找到内核模块的 text bss和 data段地址 2 在 gdb 中使用 add symbol f
  • 为什么同一个curl命令在windows和linux下输出不同的东西?

    为什么同样的curl o file https www link com 命令输出不同的东西 例如 如果我运行命令curl o source txt https www youtube com playlist list PLIx6Fwnp
  • 复制目录内容

    我想将目录 tmp1 的内容复制到另一个目录 tmp2 tmp1 可能包含文件和其他目录 我想使用C C 复制tmp1的内容 包括模式 如果 tmp1 包含目录树 我想递归复制它们 最简单的解决方案是什么 我找到了一个解决方案来打开目录并读
  • x86-64 AMD 上 CALL 指令的操作数生成

    以下是示例程序 objdump 的输出 080483b4

随机推荐

  • 控制GPIO输出——程序设计步骤【HAL】

    GPIO即通用输入输出接口 General purpose Input Output 作为输入时 读取引脚的高低电平 作为输出时 通过输出的高低电平控制外围设备 这里简单介绍GPIO的作为输出的程序设计步骤 整体思路 开启GPIO时钟 选择
  • Windows拍照报错:0xA00F424F PhotoCaptureFileCreationFailed (0x80270200)解决办法

    Windows拍照报错 0xA00F424F PhotoCaptureFileCreationFailed 0x80270200 解决办法 1 为本机照片添加库文件夹 windows 10路径 C Users Administrator A
  • C语言之指针篇【超详细讲解,带你层层深入理解指针】

    目录 一 关于指针 二 指针类型 1 整型指针的访问权限说明 2 字符指针的访问权限说明 3 指针的类型决定向前或向后一步走了多大距离 三 野指针相关知识 1 野指针的成因 指针未初始化 指针的越界访问 指针所指向的空间释放了 2 如何规避
  • 2019 CVPR oral 去模糊论文"DAVANet: Stereo Deblurring with View Aggregation"阅读笔记

    19CVPR 结果早就出来了 最近才读到的19年oral的去模糊工作 博主认真的搜了一下18年的CVPR deblurring 相关的oral为zero 底层图像复原的oral工作也很少 因此 十分兴奋看到deblurring的oral工作
  • Spring源码:PropertyValues类及属性注入二

    主代码 1 RuntimeBeanReference类型 2 RuntimeBeanNameReference类型 3 BeanDefinitionHolder类型 4 BeanDefinition类型 5 ManagedArray类型 6
  • SpringBoot中MyBatis传参的方式

    版本 SpringBoot调用MyBatis访问数据库 依赖为org mybatis spring boot 版本为2 1 2 两种调用方式 两种调用方式为 注解方式和SqlProvider方式 两种方式所遵循的规则相同 无论是否使用 Pa
  • 【php】密码正则格式校验

    密码由字母或数组组成 function is passwd v pattern 0 9a zA Z 6 16 i if preg match pattern v System FileLog FileLog write h5密码重置 tru
  • el-table渲染二级对象数组

    1 序言 项目地址如下 https gitee com liu wenxin complexELTable git 想要渲染这样的数据 el table官网给的例子都是一级对象数组 如果想要渲染二级对象数组 直接 table tableDa
  • 什么是多阶段 Docker 镜像?

    介绍 让我们从基础开始 码头工人 这是一个很棒的工具 可以让您在这些简洁的小容器中创建 部署和运行应用程序 将它们想象成微型虚拟机 但只有足够的资源来运行您的应用程序 这太棒了 因为这意味着您可以在任何平台上运行您的应用程序 从笔记本电脑到
  • Raneto

    Raneto Raneto是一个采用Node js开发的免费开源知识库平台 它使用Markdown文件来存储知识库 Raneto也可以叫作一个 静态网站生成器 因为它不需要数据库 你的所有内容都存储在 Markdown md 文件中 整个知
  • Vue2 +Element-ui实现前端页面

    1 页面项目 以一个简单的前端页面为例 主要是利用vue和element ui实现 里面涉及的主要包括 新建vue项目 一行多个输入框 页面实现等 2 项目流程 1 新建项目 首先安装nodejs 这部分在此就不讲啦 然后安装vue cli
  • 关于BIO、AIO、NIO的 区别于联系

    目录 IO BIO NIO AIO 区别及联系 各自适用场景 使用方式 IO 什么是IO 它是指计算机与外部世界或者一个程序与计算机的其余部分的之间的接口 它对于任何计算机系统都非常关键 因而所有 I O 的主体实际上是内置在操作系统中的
  • 深度学习——贝叶斯神经网络

    文章目录 前言 什么是贝叶斯神经网络 How to train BNN BNN背后的数学原理 pytorch实现BNN 参考文献 前言 本文将总结贝叶斯神经网络 首先 我将简单介绍一下什么是贝叶斯神经网络 BNN 接着我将介绍BNN是怎么训
  • Orcad Captue原理图更改后同步更新到Allegro PCB

    Cadence软件的原理图和PCB是两个软件 原理图到PCB需要创建网表 然后在PCB中放置已经建好分封装的元器件 如果对于已经画好的PCB 后期发现需要更改原理图的某个部分 原理图更改后 怎么同步更新到PCB中 而不变动原来已经布好局 布
  • MySQL备份及恢复

    目录 MySQL备份 MySQL备份方法 备份策略 mysql的完全备份 mysql的增量备份 MySQL恢复 mysql完全恢复 mysql增量备份的恢复 MySQL备份 MySQL备份是基于对MySQL的日志进行备份 且恢复也是通过日志
  • Multispectral Pedestrian Detection using Deep Fusion Convolutional Neural Networks (深度学习多光谱行人检测综述)

    Now salient detection methods most of current pedestrian detectors explored color images of good lighting and they are v
  • 基于Arduino的双向交通灯系统

    学 号 231 姓 名 福福 指导教师 赵志鹏 年 7 月 2 日 实训题目 交通灯系统 1 系统设计 设计要求 设计任务 设计基于Arduino的双向交通灯系统 实现控制和方向显示功能 性能指标要求 1 基本要求 1 按照题目要求独立完成
  • 动态显示带图片列表【Android】

    一 功能描述 1 动态获取服务器端商品信息显示 2 动态加载服务器端图片显示 二 技术点 ListView BaseAdapter JSON数据解析 Handler Thread HttpUrlConnection AsyncTask Ht
  • unity 字体 素材_教程篇

    Unity异步加载 在使用Unity引擎开发项目时 很多时候需要用到异步加载场景或资源 如需打开一个非常大的场景时需要等待 两个场景之间的一个过渡 游戏关卡的加载等等 通过添加一个进度条的方式可以很好的增强用户体验 并让用户了解场景的加载进
  • 【DevOps】Centos 7.9 安装、部署与使用 k8s集群(v1.21.3)

    卸载 k8s集群 1 平滑移除 Node kubectl get node kubectl cordon node name 不可调度 kubectl drain node name 驱逐资源 kubectl delete node nam