k8s安装及部署流程

k8s安装及部署流程

文章目录


K8s安装流程

1准备工作

1.1关闭防火墙

systemctl stop firewalld
systemctl disable firewalld

1.2关闭selinux

#临时关闭
setenforce 0 
#永久关闭
sed -i 's/enforcing/disabled/' /etc/selinux/config 

1.3关闭虚拟内存(swap空间)

#临时关闭
swapoff -a
#永久关闭
sed -ri 's/.*swap.*/#&/' /etc/fstab

1.4配置hosts文件

cat >> /etc/hosts <<EOF
192.168.233.135 k8smaster
192.168.233.136 k8snode
EOF

1.5修改iptables

原因:kubernetes的service要通过iptables来做后端pod的转发和路由
cat > /etc/sysctl.d/k8s.conf <<EOF 
net.bridge.bridge-nf-call-ip6tables=1
net.bridge.bridge-nf-call-iptables=1
EOF

注意事项:此时尚未安装k8s,故需要先进行创建

1.6安装ntpdate,进行时间同步

yum install ntpdate -y #安装ntpdate
ntpdate time.windows.com #同步时间
date #查看时间是否同步完成

注意事项:有时yum源中没有ntpdate,导致无法安装,可以修改yum源,当然也可以首先查看并比较date是否相同,如果相同则无需进行ntpdate的时间同步

2安装部署

2.1安装docker

2.1.1更新docker的yum源

wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo

注意:如果不存在wget应用,需要运行yum install wget安装

2.1.2安装指定版本的docker

yum install docker-ce-19.03.13 -y

2.1.3修改docker的镜像源,启动服务

cd /etc
mkdir docker
cd docker
vi daemon.json #docker安装后daemon.json文件尚未存在,需要手动创建
{
    
    
"registry-mirrors":["https://registry.docker-cn.com"]#此为docker国内镜像源
}
注意事项:registry.docker-cn.com有时也并不能连接上,可以采用下列国内的公共的docker镜像源:
#网易:
http://hub-mirror.c.163.com
#中国科技大学
https://docker.mirrors.ustc.edu.cn

当然,如果机器本身有梯子,上述几步可完全跳过,即不设置daemon.json

systemctl daemon-reload
systemctl restart docker

systemctl enable docker.service #启动docker服务

2.2安装k8s

2.2.1添加k8s的阿里云yum源

cat > /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg 【注意这里是空格,不是回车】
https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

2.2.2安装kubeadm,kubelet,kubectl

yum install kubelet-1.19.4 kubeadm-1.19.4 kubectl-1.19.4 -y
systemctl enable kubelet.service #启动kubelet服务

用下面的命令检查是否安装

yum list installed |grep kubelet
yum list installed |grep kubeadm
yum list installed |grep kubectl

用下面的命令检查版本

kubelet --version
各组件作用:
Kubelet:运行在集群所有节点上,负责启动POD和容器
Kubeadm:用于初始化cluster
Kubectl:k8s的命令行工具,用于部署和管理应用

2.2.3补充 注意事项

以上所有操作可在所有服务器上运行(master,node等等)
以下操作仅在master节点上运行

2.2.4部署初始化kubernetes master主节点

方法一(命令行方式):

kubeadm init \
 --apiserver-advertise-address=192.168.233.135 \ #apiserver入口,填写master节点的内网地址
 --image-repository registry.aliyuncs.com/google_containers \ # 镜像仓库
 --kubernetes-version v1.19.4 \ # 启动版本,即要下载的k8s版本
 --service-cidr=10.96.0.0/12 \ # 对外service的私网地址,不能与下面的地址或本机网络有冲突
 --pod-network-cidr=10.244.0.0/16 # 创建新的pod时分配的地址,不能与上面的地址或本机网络有冲突
 #注意事项:此步有可能报错docker service未启动,可以尝试重启
reboot

方法二(yaml文件方式):

注意事项:从这一步开始,就开始了第一个通过yaml文件配置进行各种应用、服务部署的阶段了
所以建议在一个地方新建文件夹,对后续各种的yaml文件进行分类
kubeadm.yaml文件:

apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: abcdef.0123456789abcdef #关键参数:密钥可以自己设置,注意长度
  ttl: 24h0m0s #关键参数:密钥的过期时间,依据情况可以设置长一些,设置为0s,为永不过期
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 192.168.0.85 #apiserver入口,填写master节点的内网地址
  bindPort: 6443 #apiserver入口的端口,默认6443
nodeRegistration:
  criSocket: /var/run/dockershim.sock
  name: k8smaster #这里尽量跟本地机器名一样,跟hosts设置一样
  taints:
  - effect: NoSchedule
    key: node-role.kubernetes.io/master
---
apiServer:
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {
    
    }
dns:
  type: CoreDNS
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: v1.19.4
networking:
  dnsDomain: cluster.local
  podSubnet: 10.244.0.0/16
  serviceSubnet: 10.96.0.0/12
scheduler: {
    
    }

启动方法:

kubeadm init --config kubeadm.yaml 

注意事项:启动后会在最后输出一行命令,记下这行命令,是用让其他节点进行加入的:

kubeadm join 192.168.0.85:6443 --token qavz41.zu82xtec8c4bob55 --discovery-token-ca-cert-hash sha256:9236af9eebe7a94ec75cfa37db708efcf225b0028233052147777bf4ee2e52b8

2.2.5 admin.conf相关

如果是用的root权限:

export KUBECONFIG=/etc/kubernetes/admin.conf

如果是普通的用户权限

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

注意事项:admin.conf很重要,如果想要以后在其他的从节点上运行kubectl来操控集群,则admin.conf是必须的

2.2.6 检查启动结果

kubectl get nodes #当有node显示时,则完成

2.2.7 部署flannel应用

Flannel是CoreOS 团队针对 Kubernetes 设计的一个覆盖网络(Overlay Network)工具:
在默认的Docker配置中,每个节点上的Docker服务会分别负责所在节点容器的IP分配。这样导致的一个问题是,不同节点上容器可能获得相同的内外IP地址。并使这些容器之间能够之间通过IP地址相互找到,也就是相互ping通
Flannel的设计目的就是为集群中的所有节点重新规划IP地址的使用规则,从而使得不同节点上的容器能够获得“同属一个内网”且”不重复的”IP地址,并让属于不同节点上的容器能够直接通过内网IP通信。
Flannel实质上是一种“覆盖网络(overlaynetwork)”,也就是将TCP数据包装在另一种网络包里面进行路由转发和通信,目前已经支持udp、vxlan、host-gw、aws-vpc、gce和alloc路由等数据转发方式,默认的节点间数据通信方式是UDP转发。

wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml 
kubectl apply -f kube-flannel.yml  #这里是出现的第二个yaml文件,注意专门保存
kubectl get pods -n kube-system #查询flannel是否安装成功

————————————至此,k8s部署完毕——————————————————

2.2.8 canal的安装负责网络策略

k8s集群使用flannel cni插件,由于flannel 不支持 networkpolicy网络策略进行隔离,
所以可以用calico进行networkpolicy的支持,而如果已经安装了flannel的话,则可以使用canal(flannel+calico),其中由flannel负责pod所有ip的分配,由calico负责网络策略的调度
在实际使用中,在安装flannel的基础上安装canal即可
官方页面:Install Calico for policy and flannel (aka Canal) for networking (projectcalico.org)

安装方式:kubernetes api datastore(官方推荐)
1、安装前提:--allocate-node-cidrs=true(在/etc/kubernetes/manifest/kube-apiserver.yaml)中设置,具体可以查看4.3.3中apiserver中的此项
2、下载yaml文件

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

3、应用yaml

kubectl apply -f canal.yaml

2.2.9 kube-router的安装负责网络策略(尚未测试过)

除了canal,kube-router也可以实现网络策略的使用,kube-router是一个新的k8s的网络插件,使用lvs做服务的代理及负载均衡,使用iptables来做网络的隔离策略。部署简单,只需要在每个节点部署一个daemonset即可,高性能,易维护。支持pod间通信,以及服务的代理

安装方式:

wget https://raw.githubusercontent.com/cloudnativelabs/kube-router/master/daemonset/generic-kuberouter-all-features.yaml

启用pod网络通信,网络隔离策略,服务代理所有功能

CLUSTERCIDR kube-controller-manager 启动参数 --cluster-cidr 的值
APISERVER kube-apiserver 启动参数 --advertise-address 值CLUSTERCIDR='10.244.0.0/16'APISERVER='https://11.11.11.111:6443'sed -i "s;%APISERVER%;$APISERVER;g" generic-kuberouter-all-features.yaml

sed -i "s;%CLUSTERCIDR%;$CLUSTERCIDR;g" generic-kuberouter-all-features.yaml
kubectl apply -f generic-kuberouter-all-features.yaml

删除kube-proxy

kubectl -n kube-system delete ds kube-proxy

在每个节点上执行

如果是二进制安装使用如下命令

systemctl stop kube-proxy

在每个节点上执行

清理kube-proxy留下的规则

docker run --privileged --net=host registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy-amd64:v1.10.2 kube-proxy --cleanup

查看

kubectl get pods -n kube-system
kubectl get svc -n kube-system

3基本的命令操作

可以参考kubectl 备忘单 | Kubernetes 列举了常用的 “kubectl” 命令和标志

3.1 master节点上的各种资源查看方式

节点与命名空间相关

kubectl get nodes # 查看所有节点
kubectl get namespaces # 查看所有命名空间
kubectl api-resources --namespaced=true  ##查看哪些资源在命令空间
kubectl api-resources --namespaced=false  ##查看哪些资源不在命令空间
kubectl  config set-context --current --namespace=kube-system  # 切换至kube-system的命名空间
kubectl create ns test # 创建一个叫test的命名空间

pod相关:

kubectl get pods # 查看default默认命名空间下的pods
kubectl get pods -n namespace名 # 查看在指定命名空间下的pods
kubectl get pod --selector name=redis #按selector名来查找pod
kubectl get pods --all-namespaces # 查看所有集群的所有的pod信息
kubectl get pods -o wide # 查看pods所在的运行节点
kubectl get pods -o yaml # 查看pods定义的详细信息
kubectl exec pod名 env # 查看运行的pod的环境变量
kubectl logs podname # 查看指定pod的日志
kubectl logs -f podname # 滚动查看指定pod的日志
kubectl describe pods-dasdeqwew2312-g6q8c # 查看指定pod的详细信息
(注:如果pod启动失败,如error、crashloopbackoff、imagepullbackoff等,均可以用此方法查看,排错)
kubectl get pod -l app --show-labels # 根据标签”app”筛选

#deployment相关:

kubectl get deployment # 查看deployment相关信息
kubectl rollout history deployment/nginx-deployment # 查看deployment历史修订版本

同样,其他资源还有service(服务),networkpolicy(网络策略),replicaset(副本)
在查看这些东西时,没有必要输入全名,可以输入别名,简称如下:

Nodes-no
pod-po
namespaces-ns
networkpolicy-netpol
service-svc
replicasets-rs
daemonsets-ds
statefulsets-sts
jobs-jobs
deployment-deploy
Persistentvolumes-pv
Persistentvolumeclaims-pvc
Configmaps-cm
Limitranges-ing

查看环境各项目的资源概览:

kubectl get quota --all-namespaces  -o yaml # 查看cpu和内存、存储卷容量
echo $TERM
#export TERM=dumb
#top #查看某个pod的cpu使用情况

3.2集群角色的设置

kubectl label nodes test1 node-role.kubernetes.io/master= # 设置 test1 为 master 角色
kubectl label nodes 192.168.0.92 node-role.kubernetes.io/node= # 设置 test2 为 node 角色
kubectl taint nodes test1 node-role.kubernetes.io/master=true:NoSchedule # 设置 master 一般情况下不接受负载
kubectl taint nodes k8smaster node-role.kubernetes.io/master- # master运行pod
kubectl taint nodes test1 node-role.kubernetes.io/master=:NoSchedule # master不运行pod
语法:
kubectl label nodes 节点名字 node-role.kubernetes.io/想要的roles
kubectl label nodes <node-name> <label-key>=<label-value>

#例如下面的nodeselector里面要type=k8smaster就必须对应设置一下
后面还有一个减号或等号
减号就是删除roles,等号就是增加roles

3.3资源的创建与删除

#创建

kubectl create yaml文件名 -n namespace名

#删除

kubectl delete resourc命名 resource的name -n namespace名

注意事项:用deployment部署的pod,直接删除pod是不行的,deployment会监控pod是否挂掉,所以需要删除deployment

3.4资源的标签

标签的作用:在资源间的调度时进行过滤

kubectl get nodes --show-labels # 查看资源标签(以node为例)
kubectl label node node名type=node1 # 给指定node名的资源打标签
kubectl label pods -n pod12 -l "pod-template-hash=6f5fc58db" type=pod12 # 给指定标签的资源打标签

3.5资源的进入

kubectl -n pod12 exec -it nginx-deployment-6f5fc58db-s8prx(容器名) sh # 进入容器

4资源的部署及配置

4.1 pod资源的部署方式

部署命令:

kubectl create -f nginx-pod.yaml -n pod12

Yaml方式示例nginx-pod.yaml:

apiVersion: v1 # 1.9后使用v1,之前使用v1beta1/v1beta2
kind: Pod # 资源类型
metadata:
  name: nginx # 资源名称
  labels:
    app: nginx # 预先要打的标签
spec:
  nodeSelector:
    type: k8smaster # 选择部署的节点
  containers:
  - name: nginx # 容器的名称
    image: nginx:alpine # 容器的镜像
    ports:
    - containerPort: 80 # 对service开放的端口

附:yaml所有配置项:

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    

4.2 Deployment资源的部署方式

部署命令

kubectl create -f nginx-deployment.yaml -n pod12

yaml示例:nginx-deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx # 
  replicas: 2
  template: #部署模板
    metadata:
      labels:
        app: nginx
    spec:
     containers:
     - name: nginx
       image: nginx:alpine
       ports:
       - containerPort: 80
     nodeSelector:
       type: node1 #选择在哪个节点部署
附:yaml所有配置项:
apiVersion: extensions/v1beta1
kind: Deployment
metadata: <Object>
spec: <Object>
  minReadySeconds: <integer> #设置pod准备就绪的最小秒数
  paused: <boolean> #表示部署已暂停并且deploy控制器不会处理该部署
  progressDeadlineSeconds: <integer>
  strategy: <Object> #将现有pod替换为新pod的部署策略
    rollingUpdate: <Object> #滚动更新配置参数,仅当类型为RollingUpdate
      maxSurge: <string> #滚动更新过程产生的最大pod数量,可以是个数,也可以是百分比
      maxUnavailable: <string> #
    type: <string> #部署类型,Recreate,RollingUpdate
  replicas: <integer> #pods的副本数量
  selector: <Object> #pod标签选择器,匹配pod标签,默认使用pods的标签
    matchLabels: <map[string]string> 
      key1: value1
      key2: value2
    matchExpressions: <[]Object>
      operator: <string> -required- #设定标签键与一组值的关系,In, NotIn, Exists and DoesNotExist
      key: <string> -required-
      values: <[]string>   
  revisionHistoryLimit: <integer> #设置保留的历史版本个数,默认是10
  rollbackTo: <Object> 
    revision: <integer> #设置回滚的版本,设置为0则回滚到上一个版本
  template: <Object> -required-
    metadata:
    spec:
      containers: <[]Object> #容器配置
      - name: <string> -required- #容器名、DNS_LABEL
        image: <string> #镜像
        imagePullPolicy: <string> #镜像拉取策略,Always、Never、IfNotPresent
        ports: <[]Object>
        - name: #定义端口名
          containerPort: #容器暴露的端口
          protocol: TCP #或UDP
        volumeMounts: <[]Object>
        - name: <string> -required- #设置卷名称
          mountPath: <string> -required- #设置需要挂载容器内的路径
          readOnly: <boolean> #设置是否只读
        livenessProbe: <Object> #就绪探测
          exec: 
            command: <[]string>
          httpGet:
            port: <string> -required-
            path: <string>
            host: <string>
            httpHeaders: <[]Object>
              name: <string> -required-
              value: <string> -required-
            scheme: <string> 
          initialDelaySeconds: <integer> #设置多少秒后开始探测
          failureThreshold: <integer> #设置连续探测多少次失败后,标记为失败,默认三次
          successThreshold: <integer> #设置失败后探测的最小连续成功次数,默认为1
          timeoutSeconds: <integer> #设置探测超时的秒数,默认1s
          periodSeconds: <integer> #设置执行探测的频率(以秒为单位),默认1s
          tcpSocket: <Object> #TCPSocket指定涉及TCP端口的操作
            port: <string> -required- #容器暴露的端口
            host: <string> #默认pod的IP
        readinessProbe: <Object> #同livenessProbe
        resources: <Object> #资源配置
          requests: <map[string]string> #最小资源配置
            memory: "1024Mi"
            cpu: "500m" #500m代表0.5CPU
          limits: <map[string]string> #最大资源配置
            memory:
            cpu:         
      volumes: <[]Object> #数据卷配置
      - name: <string> -required- #设置卷名称,与volumeMounts名称对应
        hostPath: <Object> #设置挂载宿主机路径
          path: <string> -required- 
          type: <string> #类型:DirectoryOrCreate、Directory、FileOrCreate、File、Socket、CharDevice、BlockDevice
      - name: nfs
        nfs: <Object> #设置NFS服务器
          server: <string> -required- #设置NFS服务器地址
          path: <string> -required- #设置NFS服务器路径
          readOnly: <boolean> #设置是否只读
      - name: configmap
        configMap: 
          name: <string> #configmap名称
          defaultMode: <integer> #权限设置0~0777,默认0664
          optional: <boolean> #指定是否必须定义configmap或其keys
          items: <[]Object>
          - key: <string> -required-
            path: <string> -required-
            mode: <integer>
      restartPolicy: <string> #重启策略,Always、OnFailure、Never
      nodeName: <string>
      nodeSelector: <map[string]string>
      imagePullSecrets: <[]Object>
      hostname: <string>
      hostPID: <boolean>
status: <Object>

4.2.1 deployment资源的扩容、缩容、升级、回滚

扩容
语法格式

kubectl scale deployment + [deploy的name] + --replicas [count] + --namespace=命名空间

命令

kubectl scale deployment nginx-test --replicas 5 --namespace=test
输出:deployment.extensions "nginx-test" scaled

缩容
命令

kubectl scale deployment nginx-test --replicas 2 --namespace=test
输出:deployment.extensions "nginx-test" scaled

滚动升级

将image: nginx:1.7.9升级为nginx:1.9.1#语法格式
kubectl scale deployment/[deploy的name] + [升级镜像] + --namespace=命名空间

#命令

kubectl set image deployment/nginx-test  nginx=nginx:1.9.1 --namespace=test
输出:deployment.apps "nginx-test" image updated

回滚
命令

kubectl rollout undo deployment/nginx-test --namespace=test
deployment.apps "nginx-test"

4.3 Service资源的部署方式

Service 的理念是将一组 Pod 端点划分为单一资源。可以配置各种方式来访问该分组。默认情况下,会获得稳定的集群 IP 地址,集群内部的客户端可以使用该 IP 地址与 Service 中的 Pod 通信。客户端向稳定 IP 地址发送请求,然后请求会被路由到 Service 的其中一个 Pod。
Service 通过选择器来识别其成员 Pod。为使 Pod 成为 Service 的成员,该 Pod 必须具有选择器中指定的所有标签。 标签是附加到对象的任意键值对

4.3.1 Service的类型

提供五种类型的 Service:
1、ClusterIP(默认):内部客户端向稳定的内部 IP 地址发送请求。
2、NodePort:客户端向使用 Service 指定的一个或多个 nodePort 值的节点的 IP 地址发送请求。
3、LoadBalancer:客户端向网络负载平衡器的 IP 地址发送请求。
4、ExternalName:内部客户端使用 Service 的 DNS 名称作为外部 DNS 名称的别名。
5、Headless:如果需要 Pod 分组,但不需要稳定的 IP 地址,则可以使用 Headless 服务。
NodePort 类型是 ClusterIP 类型的扩展。因此,NodePort 类型的 Service 具有集群 IP 地址。
LoadBalancer 类型是 NodePort 类型的扩展。因此,LoadBalancer 类型的 Service 具有集群 IP 地址以及一个或多个 nodePort 值。

4.3.2 ClusterIP 类型的 Service

apiVersion: v1
kind: Service
metadata:
  name: my-cip-service
spec:
  selector:
    app: metrics
    department: sales
  type: ClusterIP
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

4.3.3 NodePort 类型的 Service

apiVersion: v1
kind: Service
metadata:
  name: nginx3-service #service的名称
spec:
  selector:
    app: nginx3 #指定标签service要服务的pod名称
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
nodePort: 8443 #选择要暴露的端口 
  type: NodePort # 选择暴露端口的方式

外部客户端使用节点的外部 IP 地址及 nodePort 指定的 TCP 端口来调用 Service。请求将转发到 targetPort 字段指定的 TCP 端口上的其中一个成员 Pod。

例如,假设其中一个集群节点的外部 IP 地址是 203.0.113.2。那么,对于上述示例,外部客户端在 TCP 端口 32675 上调用
203.0.113.2 的 Service。请求将转发到 TCP 端口 8080 上的其中一个成员 Pod。成员 Pod 必须拥有一个侦听 TCP 端口 8080 的容器。

NodePort Service 类型是 ClusterIP Service 类型的扩展。因此,内部客户端可通过以下两种方式来调用 Service:
使用 clusterIP 和 port。
使用节点的内部 IP 地址和 nodePort。
端口的修改方式
非常重要:想暴露的端口默认为30000-32767之间,但是依旧可以修改
修改方式:vi /etc/kubernetes/manifest/kube-apiserver.yaml
添加 - --service-node-port-range=1-65535
这样就可以选择暴露30000之前的端口了

kube-apiserver.yaml:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 192.168.0.85:6443
  creationTimestamp: null
  labels:
    component: kube-apiserver
    tier: control-plane
  name: kube-apiserver
  namespace: kube-system
spec:
  containers:
  - command:
    - kube-apiserver
    - --advertise-address=192.168.0.85
    - --allow-privileged=true
    - --authorization-mode=Node,RBAC
    - --client-ca-file=/etc/kubernetes/pki/ca.crt
    - --enable-admission-plugins=NodeRestriction
    - --enable-bootstrap-token-auth=true
    - --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
    - --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
    - --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
    - --etcd-servers=https://127.0.0.1:2379
    - --insecure-port=0
    - --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt
    - --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key
    - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
    - --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
    - --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
    - --requestheader-allowed-names=front-proxy-client
    - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
    - --requestheader-extra-headers-prefix=X-Remote-Extra-
    - --requestheader-group-headers=X-Remote-Group
    - --requestheader-username-headers=X-Remote-User
    - --secure-port=6443
    - --service-account-key-file=/etc/kubernetes/pki/sa.pub
    - --service-cluster-ip-range=10.96.0.0/12
    - --tls-cert-file=/etc/kubernetes/pki/apiserver.crt
    - --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
    - --service-node-port-range=1-65535 #端口的暴露方式
    - --runtime-config=extensions/v1beta1/networkpolicies=true
    image: registry.aliyuncs.com/google_containers/kube-apiserver:v1.19.4
    imagePullPolicy: IfNotPresent
    livenessProbe:
      failureThreshold: 8
      httpGet:
        host: 192.168.0.85
    - --requestheader-extra-headers-prefix=X-Remote-Extra-
    - --requestheader-group-headers=X-Remote-Group
    - --requestheader-username-headers=X-Remote-User
    - --secure-port=6443
    - --service-account-key-file=/etc/kubernetes/pki/sa.pub
    - --service-cluster-ip-range=10.96.0.0/12
    - --tls-cert-file=/etc/kubernetes/pki/apiserver.crt
    - --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
    - --service-node-port-range=1-65535 #这个地方也要修改
    - --runtime-config=extensions/v1beta1/networkpolicies=true
    ...

4.3.4 LoadBalancer 类型的 Service

apiVersion: v1
kind: Service
metadata:
  name: my-nlb-service
spec:
  selector:
    app: metrics
    department: engineering
  type: LoadBalancer
  ports:
  - port: 80
targetPort: 8080

创建 Service 后,使用 kubectl get service -o yaml 查看其规范并查看稳定的外部 IP 地址:

spec:
  clusterIP: 10.11.242.115
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 32676
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: metrics
    department: engineering
  sessionAffinity: None
  type: LoadBalancer
  status:
    loadBalancer:
      ingress:
      - ip: 203.0.113.100

在输出中,网络负载平衡器的 IP 地址显示在 loadBalancer:ingress: 下方。外部客户端使用负载平衡器的 IP 地址和 port 指定的 TCP 端口来调用 Service。请求将转发到 targetPort 指定的 TCP 端口上的其中一个成员 Pod。因此,对于上述示例,客户端在 TCP 端口 80 上调用 203.0.113.100 的 Service。 请求将转发到 TCP 端口 8080 上的其中一个成员 Pod。 成员 Pod 必须拥有一个侦听 TCP 端口 8080 的容器。
LoadBalancer Service 类型是 NodePort 类型的扩展,而 NodePort 类型是 ClusterIP 类型的扩展

4.3.5 ExternalName 类型的 Service

ExternalName 类型的 Service 为外部 DNS 名称提供内部别名。内部客户端使用内部 DNS 名称发出请求,然后请求会被重定向到外部名称。

apiVersion: v1
kind: Service
metadata:
  name: my-xn-service
spec:
  type: ExternalName
  externalName: example.com

创建 Service 时,Kubernetes 会创建一个 DNS 名称,内部客户端可以使用该名称来调用 Service。对于上述示例,DNS 名称是 my-xn-service.default.svc.cluster.local。当内部客户端向 my-xn-service.default.svc.cluster.local 发出请求时,请求会被重定向到 example.com。

ExternalName Service 类型与其他 Service 类型完全不同。事实上,ExternalName 类型的 Service 不符合本主题开头提出的 Service 定义。ExternalName 类型的 Service 不与一组 Pod 相关联,也没有稳定的 IP 地址。相反,ExternalName 类型的 Service 从内部 DNS 名称映射到外部 DNS 名称。

4.3.6 nodePort、port、targetPort、containerPort的区别

  1. nodePort
    nodePort提供了集群外部客户端访问service的一种方式,:nodePort提供了集群外部客户端访问service的端口,即nodeIP:nodePort提供了外部流量访问k8s集群中service的入口。
    比如外部用户要访问k8s集群中的一个Web应用,那么我们可以配置对应service的type=NodePort,nodePort=30001。其他用户就可以通过浏览器http://node:30001访问到该web服务。
    而数据库等服务可能不需要被外界访问,只需被内部服务访问即可,那么我们就不必设置service的NodePort。

  2. port
    port是暴露在cluster ip上的端口,:port提供了集群内部客户端访问service的入口,即clusterIP:port。
    mysql容器暴露了3306端口(参考DockerFile),集群内其他容器通过33306端口访问mysql服务,但是外部流量不能访问mysql服务,因为mysql服务没有配置NodePort。:

  3. targetPort
    targetPort是pod上的端口,从port/nodePort上来的数据,经过kube-proxy流入到后端pod的targetPort上,最后进入容器。
    与制作容器时暴露的端口一致(使用DockerFile中的EXPOSE),例如官方的nginx(参考DockerFile)暴露80端口。

  4. containerPort
    containerPort是在pod控制器中定义的、pod中的容器需要暴露的端口。

  5. 总结
    总的来说,port和nodePort都是service的端口,前者暴露给k8s集群内部服务访问,后者暴露给k8s集群外部流量访问。从这两个端口到来的数据都需要经过反向代理kube-proxy,流入后端pod的targetPort上,最后到达pod内容器的containerPort

4.4 NetworkPolicy资源的部署方式

以下是官方示例:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy #networkpolicy的名称
namespace: default #指定要生效的ns
spec:
podSelector: # 指定对哪些pod生效
matchLabels:
  role: db # 指定对标签中role=db的pod生效
policyTypes:
- Ingress # 入站规则
- Egress # 出站规则
ingress:
- from:
- ipBlock:
    cidr: 172.17.0.0/16 # 172.17.0-255.0-255的ip可以入站
    except: # 例外规则
    - 172.17.1.0/24 # 172.17.1.0-255的ip不能入站
- namespaceSelector:
    matchLabels:
      project: myproject # 指定命名空间在myproject中的pod才可以入站
- podSelector:
    matchLabels:
      role: frontend # 标签选择器,指定只有role=frontend标签的pod可以入站
ports:
- protocol: TCP
  port: 6379
egress:
- to:
- ipBlock:
    cidr: 10.0.0.0/24
ports:
- protocol: TCP
  port: 5978

4.4.1实际举例

有3个pod,想让pod3与pod1,pod2隔离
Ip环境:

NAME                                 READY   STATUS    RESTARTS   AGE   IP            NODE   
pod/nginx-deployment-6f5fc58db-fv879      1/1     Running   1          62m   10.244.0.18   server1
pod/nginx-deployment-6f5fc58db-q9dmc     1/1     Running   1          62m   10.244.0.20   server1
pod/nginx-deployment3-d64796755-b8m7f    1/1     Running    1          62m   10.244.1.30   server2

应设置出站规则:因为入站规则会屏蔽掉外部的service访问
Yaml设置:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny12to3 #不让pod1和2访问3
  namespace: pod12
spec:
  podSelector:
    matchLabels:
      type: "pod3" #对已经打好type=pod3标签的pod生效
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
       cidr: 10.244.0.0/16 # 允许到10.244.0-255.0-255的出站
       except:
       - 10.244.0.0/24 # 不允许到10.244.0.0-255的出站
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny3to12 #不让pod3访问pod1和2
  namespace: pod12
spec:
  podSelector:
    matchLabels:
      type: "pod12" #对已经打好type=pod12标签的pod生效
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
       cidr: 10.244.0.0/16 # 允许到10.244.0-255.0-255的出站
       except:
       - 10.244.1.0/24 # 不允许到10.244.1.0-255的出站

4.4.2其他示例

默认拒绝所有出口流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {
    
    }
policyTypes:
- Egress

默认允许所有出口流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {
    
    }
policyTypes:
- Ingress
- Egress

默认拒绝所有入口流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {
    
    }
policyTypes:
- Ingress

默认允许所有入口流量

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all
spec:
podSelector: {
    
    }
ingress:
- {
    
    }
policyTypes:
- Ingress

5资源的监控-prometheus

相关网站技术资源:(prometheus监控+grafana数据展示)
Kubernetes学习之路(二十四)之Prometheus监控 - 烟雨浮华 - 博客园 (cnblogs.com)
Prometheus是一个开源的服务监控系统和时序数据库,其提供了通用的数据模型和快捷数据采集、存储和查询接口。它的核心组件Prometheus服务器定期从静态配置的监控目标或者基于服务发现自动配置的目标中进行拉取数据,新拉取到啊的 数据大于配置的内存缓存区时,数据就会持久化到存储设备当中。

部署过程如下:

5.1创建命名空间prom

git clone git://github.com/iKubernetes/k8s-prom.git
cd k8s-prom
kubectl apply -f namespace.yaml

5.2部署node_exporter负责导出节点的数据

在k8s-prom下:

kubectl apply -f node_exporter/
kubectl get pods -n prom

5.3部署prometheus-server

在k8s-prom下:

kubectl apply -f prometheus/
kubectl get all -n prom

5.4部署kube-state-metrics

在k8s-prom下:

kubectl apply -f kube-state-metrics/
kubectl get pods -n prom -o wide

5.5制作证书

在pki文件夹下:

cd /etc/kubernetes/pki/ (没有创建一个)
(umask 077; openssl genrsa -out serving.key 2048)
openssl req -new -key serving.key -out serving.csr -subj "/CN=serving"
openssl x509 -req -in serving.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -out serving.crt -days 3650
kubectl create secret generic cm-adapter-serving-certs --from-file=serving.crt=./serving.crt --from-file=serving.key -n prom
kubectl get secret -n prom

5.6部署k8s-prometheus-adapter

在k8s-prometheus-adapter下:

wget https://raw.githubusercontent.com/DirectXMan12/k8s-prometheus-adapter/master/deploy/manifests/custom-metrics-apiserver-deployment.yaml

vim k8s-prometheus-adapter/custom-metrics-apiserver-deployment.yaml #修改名称空间为prom

wget https://raw.githubusercontent.com/DirectXMan12/k8s-prometheus-adapter/master/deploy/manifests/custom-metrics-config-map.yaml #也需要修改名称空间为prom

vim k8s-prometheus-adapter/custom-metrics-config-map.yaml #修改名称空间为prom

kubectl apply -f k8s-prometheus-adapter/
kubectl get pods -n prom
#正常应该如下所示:
NAME 									  READY STATUS  RESTARTS AGE 
custom-metrics-apiserver-65f545496-l5md9 1/1 	Running 0 		7m 
kube-state-metrics-78fc9fc745-g66p8       1/1 	Running 0 		40m 
prometheus-node-exporter-6srrq             1/1 	Running 0 		1h 
prometheus-node-exporter-fftmc             1/1 	Running 0 		1h 
prometheus-node-exporter-qlr8d             1/1 	Running 0 		1h 
prometheus-server-66cbd4c6b-j9lqr         1/1 	Running 0 		53m
kubectl get svc -n prom
#正常应该如下所示:
NAME 								TYPE 		CLUSTER-IP 		EXTERNAL-IP PORT(S) AGE 
custom-metrics-apiserver 			ClusterIP 	10.99.14.141 	<none>       443/TCP 11h 
kube-state-metrics 					ClusterIP 	10.107.23.237 	<none>       8080/TCP 11h 
prometheus 							NodePort 	10.96.65.72	     <none>       9090:30090/TCP 11h 
prometheus-node-exporter 			ClusterIP    None 		     <none> 		9100/TCP 11h

最后,访问ip+nodeport端口(这里将9090暴露为了30090)即可

5.7可能会出现的问题

#如果status出现了错误,如imagepullbackoff,crashloopbackoff,errorimagepull等问题,考虑是因为yaml文件中下载海外镜像的原因,可以先用describe看一下,或者看一下日志
#举例:在kube-state-metrics文件夹下的kube-state-metrics-deploy.yaml:

image: k8s.gcr.io/google_containers/kube-state-metrics-amd64:latest
imagePullPolicy: IfNotPresent #下面的4、中有解释

其中,k8s.gcr.io要梯子才可以访问,所以kube-state-metrics-ame64无法下载下来

解决办法如下:
1、从国内镜像当中首先docker pull下来,如原来是:

docker pull  k8s.gcr.io/google_containers/kube-state-metrics-amd64:latest

现在可以改为:docker pull registry.aliyuncs.com/google_containers/kube-state-metrics-amd64:latest
2、打tag

docker tag registry.aliyuncs.com/google_containers/kube-state-metrics-amd64:latest k8s.gcr.io/google_containers/kube-state-metrics-amd64:latest

3、删除之前下载的镜像

docker rmi registry.aliyuncs.com/google_containers/kube-state-metrics-amd64:latest

4、在yaml文件下加入imagePullPolicy:IfNotPresent,保证如果镜像存在则不用重新下载
5、重新执行yaml文件即可
6、另:也可以直接修改image: k8s.gcr.io…

6 k8s-dashboard的安装

wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-rc5/aio/deploy/recommended.yaml

创建 pod

kubectl apply -f recommended.yaml
kubectl get pods --all-namespaces

删除现有的dashboard服务,dashboard 服务的 namespace 是 kubernetes-dashboard,但是该服务的类型是ClusterIP,不便于通过浏览器访问,因此需要改成NodePort型的

kubectl get svc --all-namespaces

删除

kubectl delete service kubernetes-dashboard --namespace=kubernetes-dashboard
vim dashboard-svc.yaml

内容

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  type: NodePort
  ports:
    - port: 443
      targetPort: 8443
  selector:
    k8s-app: kubernetes-dashboard

执行

kubectl apply -f dashboard-svc.yaml
vim dashboard-svc-account.yaml

结果

apiVersion: v1
kind: ServiceAccount
metadata:
  name: dashboard-admin
  namespace: kube-system
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: dashboard-admin
subjects:
  - kind: ServiceAccount
    name: dashboard-admin
    namespace: kube-system
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

执行

kubectl apply -f dashboard-svc-account.yaml
[root@master1 ~]# kubectl get secret -n kube-system |grep admin|awk '{print $1}'
输出:dashboard-admin-token-bwgjv

复制下面的 token,后面登陆的时候要用到

[root@master1 ~]# kubectl describe secret dashboard-admin-token-bwgjv -n kube-system|grep '^token'|awk '{print $2}'
eyJhbGciOiJSUzI1NiIsImtpZCI6IkhNbG1kMUhvVVQ1RlY5QnZOb0w4ZnNwZUkwQVlMVjVsa3B6bnFtQWZTS2MifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4tZ2Q0cm4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiYTg3OWNlNmMtMGJlYS00NjczLWIzZDgtNTcxZDg0YjExOGQyIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmRhc2hib2FyZC1hZG1pbiJ9.iVlfga-5mTa-Ksp-CydEmrtFjPF7aMqI4BoM3PGiChG_jM8d3La9LWLT95ekRIV6fg_OYivVqVPtwacCact2T59bwgynMSlo4FlnRIYQEMm7JtY0cEFpAaAoKMpQ0klDC4am0FuQFngiDbFWx9udiliOecAcg0ReeUrCDxCAsT2_xu1YQ1w5qDZluvEpTQtlkhC00Aj438BPz-ZHw636f17fCJji8OykMRCsjoQdCkkQzgqZPF9vB2XPGcugVyYaUHb9lVS0c7KACOTekX2UZ8IPIeGg8txH8TrYAuJP4kWF0scQIwDoRKJTysKr_VS_peq0AkG6pOgMmN163Za32A

7 从节点的加入及相关操作

7.1从节点的加入

执行以下指令即可,kube init之后:

kubeadm join 192.168.0.85:6443 --token qavz41.zu82xtec8c4bob55 --discovery-token-ca-cert-hash sha256:9236af9eebe7a94ec75cfa37db708efcf225b0028233052147777bf4ee2e52b8

一些需要注意的问题:
加入可能会失败,在网络ok的情况下,如果之前的配置没错,考虑可能是token过期,那么则需要重新生成token并加入

7.2在从节点上运行kubectl

方式:将master节点上的/etc/kubernetes/admin.conf 复制到从节点node中的/etc/kukbernetes/admin.conf

猜你喜欢

转载自blog.csdn.net/BradMoon/article/details/123123010