kubernets全套笔记

Master/node

Master核心组件: API server,Scheduler,Controller-Manager  etcd(存储组件)

Node核心组件:  kubelet(核心组件), docke(容器引擎(支持的引擎不止docker一个)), kube-proxy

Pod  Label, label selector

Label: key=value

Label Selector:

 

 

Pod:

自主式Pod

控制器管理的Pod

ReplictionController(老版本控制器)

ReplicaSet(新版本控制器)

Deployment #通过控制replicaset来控制pod,最应该掌握的控制器之一

StatefuSet

Job,Ctonjob

AddOns: 附加组件

 

环境准备:、

Master, etcd: 172.18.0.70

Node1: 172.18.0.67

Node2: 172.18.0.68

 

前提:

  1. 基于主机名通信: /etc/hosts
  2. 时间同步  要不然会出一大推乱七八糟的报错
  3. 关闭firewall和iptables.service

OS: Centos 7.3.1611 Rxtras仓库中

 

安装配置步骤:

  1. Etcd cluster, 近master节点
  2. Flannel,集群的所有节点
  3. 配置k8s的master: 仅master节点

Kubernetes-master

启动的服务:

Kube-apiserver, kube-scheduler, kube-controller-manager

  1. 配置k8s的各node节点:

Kubernetes-node

先设定启动docker服务

启动的k8s的服务

Kube-proxy, kubelet

 

补充知识:harbor 镜像仓库

参考 https://www.cnblogs.com/pangguoping/p/7650014.html

 

k8s

先准备两台机器:

172.18.0.70 master #

172.18.0.67 node1

172.18.0.68 node2

注意: 一定要做好时间同步 要不然会有一大推莫名其妙的报错

 

然后两台机器都要配置docker和k8s的yum源

#docker18.09版本和k8s1.15.3版本

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

https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/

直接都使用阿里的镜像源

 

[root@master ~]# yum list docker-ce --showduplicates | sort -r

#如果对版本有要求可以使用这个查看  18.09,安装对应的包

所有机器都安装

[root@master ~]# yum install docker-ce-18.09.3-3.el7

 

yum -y install  kubelet kubeadm kubectl(api命令行工具)

 

然后准备启动docker,在启动docker之前建议先定义一个环境变量 随便另起一行写

[root@master ~]# vim /usr/lib/systemd/system/docker.service

Environment="HTTPS_PROXY=http://www.ik8s.io:10080""

#意思是我们访问docker服务的时候通过代理下载相关的镜像文件

Environment="NO_PROXY=127.0.0.8,172.18.0.0/16"   #不用代理 本机

:wq

docker国内加速

mkdir -p /etc/docker

vim /etc/docker/daemon.json

{

  "registry-mirrors": ["https://lvb4p7mn.mirror.aliyuncs.com"]

}

上面这个貌似不太好用,

#!/bin/bash

# download k8s 1.15.3 images

# get image-list by 'kubeadm config images list --kubernetes-version=v1.15.3'

# gcr.azk8s.cn/google-containers == k8s.gcr.io

 

images=(

kube-apiserver:v1.15.3

kube-controller-manager:v1.15.3

kube-scheduler:v1.15.3

kube-proxy:v1.15.3

pause:3.1

etcd:3.3.10

coredns:1.3.1

)

 

for imageName in ${images[@]};do

    docker pull gcr.azk8s.cn/google-containers/$imageName

    docker tag  gcr.azk8s.cn/google-containers/$imageName k8s.gcr.io/$imageName

    docker rmi  gcr.azk8s.cn/google-containers/$imageName

Done

#使用此脚本可以避免因为镜像源的问题!!!非常重要!!!

 

加载环境变量

[root@master ~]#  systemctl daemon-reload

 

启动docker并使用docker info 查看

[root@master ~]# systemctl start docker && docker info

 

 

[root@master ~]#

#默认是1就不用改

[root@master ~]# rpm -ql kubelet

/etc/kubernetes/manifests #清单目录

/etc/sysconfig/kubelet #配置文件

/usr/bin/kubelet

/usr/lib/systemd/system/kubelet.service

 

[root@master ~]# systemctl enable kubelet.service #设置成开机自启动就可以了

[root@master ~]# systemctl enable docker

 

[root@master ~]# kubelet init --help

#准备初始化

 

要把swap交换分区关了!!!!!!!!

 

初始化:

[root@master ~]# kubeadm init --kubernetes-version=v1.15.3 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12

##ps: 如果因为镜像问题可以使用上面的脚本执行,直接拉取镜像

 

成功之后会有以下几条命令,执行一下   注意一定不要忘记执行!!

  mkdir -p $HOME/.kube

  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

  sudo chown $(id -u):$(id -g) $HOME/.kube/config

初始化完成之后会有一段token哈希值,加入集群用的非常重要,可以把他先保存下来,如下:

kubeadm join 172.18.0.70:6443 --token nsezuu.f8xhql0lmz262tqv \

    --discovery-token-ca-cert-hash sha256:c98f345addbb9a585d1e9edf3f584c9dcee4dbb847a63392dc2ba444e77ec0a7

[root@master ~]# docker images

REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE

k8s.gcr.io/kube-proxy                v1.15.3             232b5c793146        8 days ago          82.4MB

k8s.gcr.io/kube-apiserver            v1.15.3             5eb2d3fc7a44        8 days ago          207MB

k8s.gcr.io/kube-controller-manager   v1.15.3             e77c31de5547        8 days ago          159MB

k8s.gcr.io/kube-scheduler            v1.15.3             703f9c69a5d5        8 days ago          81.1MB

k8s.gcr.io/coredns                   1.3.1               eb516548c180        7 months ago        40.3MB

k8s.gcr.io/etcd                      3.3.10              2c4adeb21b4f        9 months ago        258MB

k8s.gcr.io/pause                     3.1                 da86e6ba6ca1        20 months ago

 

成功之后在node1和node2上面都安装—

[root@node1 ~]# yum install docker-ce-18.09.7-3.el7 kubectl.x86_64 kubelet.x86_64 kubeadm.x86_64

[root@node2 ~]# yum install docker-ce-18.09.7-3.el7 kubectl.x86_64 kubelet.x86_64 kubeadm.x86_64

 

 

swap没关的话就忽略swap参数

vim /etc/sysconfig/kubelet

KUBELET_EXTRA_ARGS="--fail-swap-on=false"

KUBE_PROXY_MODE=ipvs

 

 

[root@master ~]# kubectl get cs #查看组件信息

NAME                 STATUS    MESSAGE             ERROR

scheduler            Healthy   ok                  

controller-manager   Healthy   ok                  

etcd-0               Healthy   {"health":"true"}

 

[root@master ~]# kubectl get nodes

NAME     STATUS     ROLES    AGE   VERSION

master   NotReady   master   32m   v1.15.3

#这里的状态信息显示还未准备好是因为缺少一个重要组件flannel

 

在git上查找flannel获取以下命令:

[root@master ~]# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

#这是一个在线的部署清单,基于此清单下载镜像flannel

 

[root@master ~]# kubectl get node

NAME     STATUS   ROLES    AGE   VERSION

master   Ready    master   41m   v1.15.3

#现在就已经准备好了

 

[root@master ~]# kubectl get ns #查看名称空间

NAME              STATUS   AGE

default           Active   43m

kube-node-lease   Active   43m

kube-public       Active   43m

kube-system       Active   43m

 

 

把master的配置文件分别拷给node1和node2

[root@master ~] scp /usr/lib/systemd/system/docker.service node1:/usr/lib/systemd/system/docker.service

[root@master ~]# scp /usr/lib/systemd/system/docker.service node2:/usr/lib/systemd/system/docker.service

 

[root@master ~]# scp /etc/sysconfig/kubelet node1:/etc/sysconfig/kubelet

[root@master ~]# scp /etc/sysconfig/kubelet node2:/etc/sysconfig/kubelet

 

 

分别在node1和node2上面启动docker并设置成开启自启

[root@node1 ~]# systemctl start docker #启动docker

[root@node1 ~]# systemctl enable docker.service kubelet.service #设置成开启自启

[root@node2 ~]# systemctl start docker #启动docker

[root@node2 ~]# systemctl enable docker.service kubelet.service #设置成开启自启

 

[root@node1 ~]# kubeadm join 172.18.0.70:6443 --token k0q4vt.2ok77anvdhzip6s8 --discovery-token-ca-cert-hash sha256:77b7364b7fc2c886aa889488d3c06d6c1f3a8a1cfc48a8857354afa749c37630 --ignore-preflight-errors=Swap

[root@node2 ~]# kubeadm join 172.18.0.70:6443 --token k0q4vt.2ok77anvdhzip6s8 --discovery-token-ca-cert-hash sha256:77b7364b7fc2c886aa889488d3c06d6c1f3a8a1cfc48a8857354afa749c37630 --ignore-preflight-errors=Swap

#加入集群

 

----------------------------------------------------------------------------------------------------------

 

 

 

[root@master ~]# kubectl describe node master #查看节点的详细信息,比较常用

[root@master ~]# kubectl cluster-info #查看集群信息

 

 

使用k8s进行增删改查

测试:

[root@master ~]# kubectl run nginx-ceshi --image=nginx --port=80 --replicas=1

#启动一个nginx   pod

[root@master ~]# kubectl get pod #查看pod

NAME                           READY   STATUS              RESTARTS   AGE

nginx-ceshi-748587595b-975t7   0/1     ContainerCreating   0          8s

 

[root@master ~]# kubectl get svc #查看服务

NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE

kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   93m

myapp        ClusterIP   10.97.57.166    <none>        80/TCP    22s

nginx        ClusterIP   10.108.78.248   <none>        80/TCP    72m

 

[root@master ~]# kubectl scale --replicas=5 deployment myapp

#扩容副本,后面数值多少就是几个副本

[root@master ~]# kubectl run client1 --image=busybox --replicas=1 -it --restart=Never

#加一个-it表示创建完直接以交互式方式进去,创建一个客户端进行测试

/ # wget -O - -q 10.244.1.5/hostname.html #查看是从哪个节点上运行的

myapp-84cd4b7f95-mj6k6

 

 

[root@master ~]# kubectl describe deployment nginx-ceshi

#查看选择器详细信息

[root@master ~]# kubectl get deployment -w

#-w实时查看

[root@master ~]# kubectl set image deployment myapp myapp=ikubernetes/myapp:v2

deployment.extensions/myapp image updated

#使用set image进行版本升级

[root@master ~]# kubectl rollout undo deployment myapp

#使用rollout out进行回滚版本

[root@master ~]# kubectl edit svc myapp

##修改svc内容

27:   type: NodePort

#大约27行,吧他修改为NodePort,就可以使用外网访问了,大小写不能错!

[root@master ~]# kubectl get svc #修改完之后使用get svc查看就会发现多一个端口

NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE

kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        155m

myapp        NodePort    10.97.57.166    <none>        80:30257/TCP   62m

 

 

 

 

删除node节点:

一共分两步:

1.排干此节点

kubectl drain 节点名称 --delete-local-data --force --ignore-daemonsets   

2.删除此节点

kubectl delete node 节点名称

 

 

Yaml:

具体可以参考:https://www.cnblogs.com/LiuQizhong/p/11536127.html

创建资源的方法:

apiserver仅接受JSON格式的资源定义;

yaml格式提供配置清单,apiserver可自动 将其转化为JSON格式,而后再提交。

大部分资源的配置清单:

[root@master ~]# kubectl explain pod #查看字段,相当于一个帮助

[root@master ~]# kubectl explain pods.status

##查看字段的详细帮助

apiversion: group/version

kind: 资源类别

metadata: 元数据

name

namespace

Latels

Annotations

每个资源的引用PATH

/api/GROUP/VERSION/namespeaces/NAMESPEACE/TYPE/NAME

Sepc: 期望的状态

Status: 当前状态,current state, 这五个一级字段由kubernetes集群维护;

 

下面是创建了一个pod里面有两个容器:格式注意下 yaml文件

apiVersion: v1

kind: Pod

metadata:

  name: pod-demo

  namespace: default

  labels:

    app: myapp

    tier: frontend

spec:

  containers:

  - name: myapp

    image: ikubernetes/myapp:v1

  - name: busybox

    image: busybox:latest

    command:

    - "/bin/sh"

    - "-c"

    - "echo $(date) >> /usr/share/nginx/html/index.html; sleep 5"

 

 

[root@master yamls]# kubectl create -f pod-damo.yaml

#根据清单创建pod

[root@master yamls]# kubectl delete -f pod-damo.yaml

[root@master yamls]# kubectl delete pods pod-demo

#删除pod

 

Key=value 键名和键值都必须小于63个字符

Key只能使用: 字母  数字 下划线  点号    , 只能使用字母或数字开头

Value 可以为空,键值不能为空,只能以字母或数字开头及结尾,之间可使用

[root@master yamls]# kubectl get pod -l app #-l标签过滤

[root@master yamls]# kubectl label pods pod-demo release=ccc ##打标签

[root@master yamls]# kubectl get pods -l app --show-labels #查看

 

节点选择器:

   nodeSelector: yaml参数指定在哪个标签的node上运行,和containers平行

KEY=VALUE

   NodeName :

 

标识:

annotations: #与label不同的地方在于,它不能用于挑选资源对象,仅用于为对象提供“元数据”,,写在metadata里面,如下

 

使用kubectl describe pods pod名字 查看

 

 

----------------------------------------------------------------------------------------------------------

 

 

Pod的生命周期:

状态: Pending(挂起), Running,Failed,Succeeded,Unknown

 

探针:

探针是由kubelet对容器执行的定期诊断,要执行诊断,kubelet调用由容器实现的Handler,有三种类型的探针:

探测方式:

LivenessProbe(存活探测):  指示器是否正在运行。如果存活探测失效,则kubelet会杀死容器,并且容器将受到其重启策略的影响,如果容器不提供存活探针,则默认状态为Success

readinessProbe(就绪与否): 指示容器是否准备好服务请求,如果就绪探测失效,断点控制器将从与Pod匹配的所有service的端点中删除该Pod的ip地址。初始延迟之前的就绪状态Failure。如果容器不提供就绪探针,则默认状态为success

 

 

探针类型有三种:

ExecAction  TCPSocketAction    HTTPGetAction

ExecAction 在容器内执行指定的命令,如果命令退出时返回码为0则认为诊断成功。

TCPSocketAction 对指定端口上的容器的IP地址进行TCP检查。如果端口打开,则诊断被认为是成功的

HTTPGetAction 对指定的端口和路径上的容器的IP地址执行HTTP GET 请求。如果响应的状态码大于等于200 且小于 400, 则诊断被认为是成功的

 

 

 

 

Pod生命周期中的重要行为:

初始化容器

容器探测

Liveness(存活性探测)

Readinessi(就绪与否)

--必须做的

 

示例:

 

Init代表延时

Per代表多少秒检测一次

 

 

Livenessprobe-HTTPGetAction:

 

 

livenessProbe-tcp

 

 

 

 

 

----------------------------------------------------------------------------------------------------------

启动或退出动作:

[root@master ym]# kubectl explain pods.spec.container.lifecycle #查看pod生命周期帮助

 

 

回顾: Pod

  apiVersion, kind, metadata, status(只读)

 

spec:

containers:

nodeSelector

nodeName

restartPolicy: #重启策略

Always, Never, OnFailure

 

containers:

    name

image

imagePullPolicy:    Always   Never  IfNotPresent

ports:

name

contarnerPort #暴露端口

livenessProbe #存活性探测

readlinessProbe #就绪状态探测

Liftcycle #启动或退出动作

 

ExecAction: exec

TCPocketAction: tcpSocket

HTTPGetAction: httpGet

 

 

Pod 控制器

ReplictionController(老版本控制器)

ReplicaSet(新版本控制器) #支持扩容,直接编辑yaml实时文件replicas

[root@master ~]# kubectl edit rs myapp  保存即生效

Deployment      #通过控制replicaset来控制pod,最应该掌握的控制器之一

DaemoSet #控制每个node上都有一个pod副本

Job #一次性

Cronjob

StatefulSet #有状态

 

声明式编程(deployment) apply(优)    create

命令式编程(rs) create(优)    apply

 

[root@master ~]# kubectl explain rs #查看新版本控制器的手册

 

 

使用ReplicaSet控制器创建的yaml

apiVersion: apps/v1

kind: ReplicaSet

metadata:

  name: myapp

  namespace: default

spec:

  replicas: 2

  selector:

      matchLabels:

          app: myapp

          release: canary

  template:

     metadata:

         name: myapp-pod

         labels:

             app: myapp

             release: canary

     spec:

        containers:

        - name: myapp-container

          image: ikubernetes/myapp:v1

          ports:

          - name: http

            containerPort: 80

 

 

使用Deployment控制器创建pod

apiVersion: apps/v1

kind: Deployment

metadata:

  name: myapp-deploy

  namespace: default

spec:

  replicas: 2

  selector:

    matchLabels:

      app: myapp

      release: canary

  template:

    metadata:

      labels:

        app: myapp

        release: canary

    spec:

      containers:

      - name: myapp

        image: ikubernetes/myapp:v1

        ports:

        - name: http

          containerPort: 80

 

[root@master ~]# kubectl apply -f deplo.yaml

[root@master ~]# kubectl get deploy

[root@master ~]# kubectl get rs

如果想要扩容副本数,直接用vim编辑yaml文件 然后再执行apply -f 创建,apply可以重复创建

 

[root@master ~]# kubectl describe deploy myapp-deploy  #查看详细信息

 

改文件也可以使用打补丁的方式:

[root@master ~]# kubectl patch deploy myapp-deploy -p '{"spec":{"replicas":6}}'

 

[root@master ~]# kubectl explain deploy.spec.strategy.rollingUpdate #查看帮滚动更新策略帮助

  strategy:

    rollingUpdate:

      maxSurge: 1

      maxUnavailable: 0

 

滚动更新:

1 直接修改yaml文件然后apply执行就可以

2 如果只更新镜像版本 可以使用 kubectl set image

[root@master ~]# kubectl set image deploy myapp-deploy myapp=ikubernetes/myapp:v3

                 [root@master ~]# kubectl set image deploy myapp-deploy myapp=ikubernetes/myapp:v3 && kubectl rollout pause deploy myapp-deploy #金丝雀发布

 

[root@master ~]# kubectl get rs -o wide #查看历史版本

 

回滚:

           [root@master ~]# kubectl rollout undo -h

           [root@master ~]# kubectl rollout history deploy myapp-deploy   #查看版本

         [root@master ~]# kubectl rollout undo deploy/myapp-deploy --to-revision=1

 

 

 

使用DamoSet控制器 实例:

[root@master ~]# kubectl explain ds ds缩写   每个node运行一个pod

apiVersion: apps/v1

kind: Deployment

metadata:

  name: redis

  namespace: default

spec:

  replicas: 1

  selector:

    matchLabels:

      app: redis

      role: logstor

  template:

    metadata:

      labels:

        app: redis

        role: logstor

    spec:

      containers:

      - name: redis

        image: redis:4.0-alpine

        ports:

        - name: redis

          containerPort: 6379

 

--- #用三横杠隔开就可以写在同一个yaml文件里

apiVersion: apps/v1

kind: DaemonSet

metadata:

  name: myapp-ds

  namespace: default

spec:

  selector:

    matchLabels:

      release: stable

      app: filebeat

  template:

    metadata:

      labels:

        app: filebeat

        release: stable

    spec:

      containers:

      - name: filebeat

        image: ikubernetes/filebeat:5.6.5-alpine

        env:

        - name: REDIS_HOST

          value: redis.default.svc.cluster.local

        - name: redis_log

          value: info+

 

两个pod之前联动靠svc

 

 

Job控制器

 

 

 

Conjob控制器案例:

 

 

 

 

Service:

工作模式: userspace, iptables, ipvs

Userspace: 1.1

iptables: 1.10

Ipvs: 1.11+

类型:

ExternalName,ClusterIP(集群内部), NodePort, and LoadBalancer

NodePort:

过程:Client-->NodeIP:NodePort-->ClusterIP:ServicePort-->PodIP:contarinersPort

资源记录:

SVC_NAME. NS_NAME DAMAIN.LTD

Svc.Cluster.Local

Redis.default.svc.cluster.local

 

Svc通过标签关联pod

案列:

·

 

Headless service(无头服务)

有时不需要或不想要负载均衡,以及单独的service ip 。遇到这种情况,可以通过指定cluster ip(spec.cluster IP)的值为“None”来创建headless service。这类service并不会分配cluster IP,kube-proxy不会处理它们,而且平台也不会为它们进行负载均衡和路由

 

实例:

 

 

NodePort:

 

 

  Ingress-nginx

Ingress-nginx: https://kubernetes.github.io/ingress-nginx/deploy/

-------------------------------------------------------------------------------------------

存储卷:

介绍:

容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题,首先,当容器奔溃时,kubelet会重启它,但是容器中的文件将丢失--容器以干净的状态(镜像最初的状态)重新启动,其次在pod中同时运行多个容器时,这些容器之前通常需要共享文件。Kubernetes中的volume抽象就很好的解决了这些问题

 

Kubernetes支持以下类型的卷:

 

SAN(本地存储): ISCSI

NAS(网络存储): nfs, cifs

分布式存储: glusterfs, rbd,  cephfs

云存储:EBS(亚马逊的),Azure Disk(微软的)

# Kubectl explain pods.spec.volumes    这里显示它支持哪些存储

[root@master ~]# kubectl explain pods.spec.volumes.emptyDir

[root@master ~]# kubectl explain pods.spec.containers.volumeMounts

apiVersion: v1

kind: Pod

metadata:

  name: pod-demo

  namespace: default

  labels:

    app: myapp

    tier: frontend

  annotations:

    magedu.com/created-by: "cluster admin"

spec:

  containers:

  - name: myapp

    image: ikubernetes/myapp:v1

    ports:

    - name: http

      containerPort: 80

    - name: https

      containerPort: 443

    volumeMounts:

    - name: html

      mountPath: /data/web/html

  - name: busybox

    image: busybox:latest

    imagePullPolicy: IfNotPresent

    command:

    - "/bin/sh"

    - "-c"

    - "sleep 7200"

    volumeMounts:

    - name: html

      mountPath: /data/

  volumes:

  - name: html

    emptyDir: {}

 

hostPath: 节点级存储   缺点节点坏了,数据也就没了

Hostpath卷将主机节点的文件系统中的文件或目录挂载到集群中

Hostpath的用途如下:

 

 

示例:

apiVersion: v1

kind: Pod

metadata:

  name: pod-vol

  namespace: default

spec:

  containers:

  - name: myapp

    image: ikubernetes/myapp:v1

    volumeMounts:

    - name: html

      mountPath: /usr/share/nginx/html/

  volumes:

  - name: html

    hostPath:

      path: /data/pod/volume1

      type: DirectoryOrCreate

 

NFS: 网络持久化存储

 

 

PVC:

概念:

PersistentVolume(pv)

是由管理员设置的存储,它是集群的一部分。就像节点是集群中的资源一样,pv也是集群中的资源。Pv是volume之类的卷插件,但具有独立于使用pv的pod的生命周期。此api对象包含存储实现的细节,即NFS iscsi或特定于云供应商的存储系统

 

PersistentVolumeClaim(pvc)

是用户存储的请求,它与pod相似。Pod消耗节点资源,pvc消耗pv资源。Pod可以请求特定级别的资源(cpu或内存)。它声明可以请求特定的大小和访问模式(例如,可以以读/写或一次货只读多次模式挂载)

 

绑定:

Master中的控制环路监视新的pvc,寻找匹配的pv(如果可能),能将它们绑定在一起,如果为新的pvc动态调配pv,则该环路将始终将该pv绑定到pvc。否则,用户总户得到他们请求的存储。但是容量可能超出要求的数量,一旦pv和pvc绑定后,pvc绑定是排他性的,不管他们是如何绑定的。Pvc跟pv绑定是一对一的映射关系。

 

状态:

l Available(可用) ---- 一款空闲资源还没有被任何声明绑定

l Bound(已绑定) --- 卷已经被声明绑定

l Released(已释放) --- 声明被删除,但是资源还未被集群重新声明

l Failed(失败)  ---  该卷的自动回收失败

 

Pvc也是kubernetes里标准的资源

[root@master ~]# kubectl explain pvc.spec

accessModes #访问模式:

ReadWriteOnce: 单路读写

ReadOnlyMany: 多路只读

ReadWriteMany:  多路读写

 

resources #资源限制

Selector #标签选择器

storageClassName #存储类

volumeMode #存储卷的模式

volumeName #存储卷的名字

 

环境准备:

在所有机器上都安装nfs-utils

以node2作为nfs服务器

在node2上创建五个挂载目录 : [root@node2 ~]# mkdir v{1..5}

[root@node2 ~]# vim /etc/exports

/root/v1   172.18.0.0/16(rw)

/root/v2   172.18.0.0/16(rw)

/root/v3   172.18.0.0/16(rw)

/root/v4   172.18.0.0/16(rw)

/root/v5   172.18.0.0/16(rw)

 

创建pv:  如下

apiVersion: v1

kind: PersistentVolume

metadata:

  name: pv001

  labels:

    name: pv001

spec:

  nfs:

    path: /root/v1

    server: node2

  accessModes: ["ReadWriteMany","ReadWriteOnce"] #设置访问类型。必须要写

  capacity:

    storage: 1Gi #大小

---

apiVersion: v1

kind: PersistentVolume

metadata:

  name: pv002

  labels:

    name: pv002

spec:

  nfs:

    path: /root/v2

    server: node2

  accessModes: ["ReadWriteMany","ReadWriteOnce"]

  capacity:

    storage: 2Gi

[root@master vl]# kubectl apply -f pv.yaml

persistentvolume/pv001 created

persistentvolume/pv002 created

。。。

[root@master vl]# kubectl get pv

NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY(回收策略)   STATUS      CLAIM   STORAGECLASS   REASON   AGE

pv001   1Gi        RWO,RWX        Retain           Available                                   5s

pv002   2Gi        RWO,RWX        Retain           Available                                   5s

。。。。

 

创建pvc

[root@master vl]# vim pvc.yaml 如下

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

  name: mypvc

  namespace: default #pvc有命名空间,pv没有

spec:

  accessModes: ["ReadWriteMany"]

  resources:

    requests:

      storage: 1Gi

---

apiVersion: v1

kind: Pod

metadata:

  name: pod-pvc

  namespace: default

  labels:

    app: myapp

spec:

  containers:

  - name: mypvc

    image: ikubernetes/myapp:v1

    volumeMounts:

    - name: mydisk

      mountPath: /data/wengwengweng

  volumes:

  - name: mydisk

    persistentVolumeClaim:

      claimName: mypvc

 

[root@master vl]# kubectl get pvc

NAME    STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE

mypvc   Bound绑定    pv001    1Gi        RWO,RWX                       2m58s

 

Pvc是存储在etcd中,就算pod死机,数据也不会丢失

 

 

当绑定pv的pvc删掉之后 想要回收此pv  可以使用edit pv   删掉ChaimRef这一行 就可以了

------------------------------------------------------------------------------------------------------

 

configmap

配置容器化应用的方式:

      1 自定义命令行参数

           Args:

      2  把配置文件直接焙进镜像

      3  环境变量

      4  存储卷

[root@master volume]# kubectl create configmap --help #查看configmap帮助信息

[root@master ~]# kubectl create configmap nginx.cconf --from-file=./nginx.cconf

#创建文件式的cm

[root@master ~]# kubectl create configmap nginxport --from-literal=nginx_pory=80

#简单的cm

 

configmap是名称空间级别的资源 直接搜索:

[root@master ~]# kubectl explain cm

 

以环境变量的方式注入到容器里:

 

 

以挂载的方式:

 

支持edit动态修改

[root@master ~]# kubectl edit cm cm名

 

secret

Secret存在的意义:

   Secret解决了密码,token,密钥等敏感数据的配置问题,而不需要把這额敏感数据暴露到镜像或pod spec中。Secret可以以volume或者环境变量的方式使用

 

Secret有三种类型:

Service account:  用来访问k8s API,由k8s自动创建,并且会自动挂载到Pod的/usr/secrets/kubernetes.io/serviceaccount目录中

Opaque:  base64编码格式的secret,用来存储密码,密钥等    安全性不怎么高,一条命令就可以解开(base64 -d)

Kubernetes.io/dockerconfigjson: 用来存储私有docker regisry的认证信息

 

 

[root@master ~]# kubectl create secret --help

docker-registry #保存认证信息

generic #通用的

tls #私钥类型

 

 

和configmap很相似

以环境变量方式注入:

 

注意以这种方式注入的密码都是解码之后的,安全性不高

 

 

 

 

如果支持dry-run的方式 可以使用-o yaml  来生成一个yaml框架!

 

 

使用secret做私有镜像认证:

命令里的大写代表变量

 

----------------------------------------------------------------------------------------------------------

Statefulset控制器

  1. 稳定且唯一的网络标识符
  2. 稳定且持久的存储
  3. 有序,平滑地部署和扩展
  4. 有序的滚动更新

一个典型的statefulset应该由三个组件组成:  headless(必须是一个无头服务)

Statefulset

volumeclaimTemplate

Sts为每个pod副本创建了一个DNS域名,这个域名的格式为: $(podname).(headless service name),也就意味着服务间是通过pod域名来通信而非pod IP ,因为opd所在的node发生故障时,pod会飘逸到其它node上,pod IP会发生变化,但是pod域名不会有变化

因为懒:

 

 

Statefulset的启停顺序:

l 有序部署:部署statefulset时,如果有多个Pod副本,它们会被顺序地创建(从0到N-1)并且在下一个pod运行之前所有之前的pod必须都是running和ready状态

l 有序删除: 当pod被删除时,它们被终止的顺序是从N-1到0

l 有序扩展: 当对pod执行扩展操作时,与部署一样,它前面的pod必须都处于running和ready状态

[root@master ~]# kubectl explain sts #查看控制器的帮助,简称

apiVersion: v1

kind: Service

metadata:

  name: myapp

  labels:

    app: myapp

spec:

  ports:

  - port: 80

    name: web

  clusterIP: None

  selector:

    app: myapp-pod

 

---

apiVersion: apps/v1

kind: StatefulSet

metadata:

  name: myapp

spec:

  serviceName: myapp

  replicas: 3

  selector:

    matchLabels:

      app: myapp-pod

  template:

    metadata:

      labels:

        app: myapp-pod

    spec:

      containers:

      - name: myapp

        image: ikubernetes/myapp:v1

        ports:

        - containerPort: 80

          name: web

        volumeMounts:

        - name: myappdata

          mountPath: /usr/share/nginx/html

  volumeClaimTemplates:

  - metadata:

      name: myappdata

    spec:

      accessModes: ["ReadWriteOnce"]

      resources:

        requests:

          storage: 10Gi

 

sts也支持动态更新,动态扩容

 

 

 

 

 

----------------------------------------------------------------------------------------------------------

 

 

认证

认证 ---->   授权-----> 准入控制

 

授权用户:

ServiceaccessountName 授权名 写在spec下面

创建sa: kubectl create serviceaccount admin

 

 

 

Dashboard:

[root@master ~]# kubectl proxy --port=8080

[root@master ~]# curl http://localhost:8080/ #查看各种资源

 

  1. 部署:

(1) [root@master ~]# Kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml

(2) 将service改为Nodeport

[root@master ~]# kubectl patch svc kubernetes-dashboard -p '{"spec": {"type": Nodeport}}' -n kube-system

要使用https的方式访问

(3) 认证:

认证时的账号必须为serviceaccount,被dashboard pod拿来由kubernetes进行认证

token:

(1)创建ServiceAccount,根据其管理目标,使用rolebinding或clusterrolebinding绑定至合理role或

clusterrole;

(2)获取到此ServiceAccount的secret,查看secret的详细信息,其中就有token;

kubeconfig: 把ServiceAccount的token封装为kubeconfig文件

(1)创建ServiceAccount,根据其管理目标,使用rolebinding或clusterrolebinding绑定至合理role或

clusterrole;

(2)kubectl get secret | awk '/^ServiceAccount/{print $1}'

KUBE_TOKEN=$(kubectl get secret SERVCIEACCOUNT_SERRET_NAME -o jsonpath={.data.token} |

base64 -d)

(3)生成kubeconfig文件

kubectl config set-cluster --kubeconfig=/PATH/TO/SOMEFILE

kubectl config set-credentials NAME --token=$KUBE_TOKEN --kubeconfig=/PATH/TO/SOMEFILE

kubectl config set-context

kubectl config use-context

 

 

令牌认证:

[root@master ~]# kubectl create serviceaccount dashboard-admin -n kube-system

#先创建一个用户

[root@master ~]# kubectl create clusterrolebinding dashboard-cluster-admin --clusterrole=clu

ster-admin --serviceaccount=kube-system:dashboard-admin  #与集群角色进行绑定,左侧名称空间,右侧账号

[root@master ~]# kubectl get secret #找到刚创建角色的token

[root@master ~]# kubectl describe secret dashboard-admin-token-ctjgn -n kube-system

   把查到的token信息复制到网页上完成登入

Config认证:

[root@master ~]# kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --server="https://172.18.0.70:6443" --embed-certs=true --kubeconfig=/root/def-ns-admin.conf

 

[root@master ~]# kubectl config view --kubeconfig=/root/def-ns-admin.conf

[root@master ~]# DEF_NS_ADMIN_TOKEN=$(kubectl get secret def-ns-admin-token-v4wxn -o jsonpath={.data.token} | base64 -d) #知道它的token并解码赋值给变量

 

[root@master ~]# kubectl config set-credentials def-ns-admin --token=$DEF_NS_ADMIN_TOKEN --kubeconfig=/root/def-ns-admin.conf #把token传进去

 

[root@master ~]# kubectl config set-context def-ns-admin@kubernetes --cluster=kubernetes --user=def-ns-admin --kubeconfig=/root/def-ns-admin.conf

 

[root@master ~]# kubectl config use-context def-ns-admin@kubernetes --kubeconfig=/root/def-ns-admin.conf

完成! 现在的配置文件可以下载下去,传到网页上就可以用了

 

----------------------------------------------------------------------------------------------------------

 

 

 

授权插件:

Node, ABAC , RBAC, Webhook

 

Kubernetes集群的管理方式:

  1. 命令式: create, run, expose, delete。。。
  2. 命令式配置文件: create -f create -f /PATH/TO/RESOURCE_CONFIGURATION_FILE, delete -f, replace -f

3、声明式配置文件: apply -f, patch,

 

----------------------------------------------------------------------------------------------------------

 

网络插件calico(网络策略)

Calico作为网络插件使用工作于192.168.0.0/16网段

 

官网文档:

https://docs.projectcalico.org/v3.9/getting-started/kubernetes/installation/flannel

   选择使用calico用于网络策略,flannel用于网络

 

部署:

[root@master ~]# kubectl apply -f https://docs.projectcalico.org/v3.9/manifests/canal.yaml

[root@master ~]# kubectl get pods -n kube-system #查看是否安装

 

使用:

[root@master ~]# kubectl explain networkpolicy.spec

egress 出站

ingress 入站

potSelector 选择哪个pod

policyTypes 策略

 

基于名称空间的网络策略

拒绝所有入站:

 

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: dey-all-ingress

spec:

  podSelector: {}

  policyTypes:

  - Ingress #拒绝所有入站

[root@master ~]# kubectl apply -f ingress.yaml -n dev -n  代表指定名称空间

[root@master ~]# kubectl get netpol -n dev #查看策略

 

放行所有进站:

 

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: dey-all-ingress

spec:

  podSelector: {}

  ingress:

  - {}           #写上之后默认放行所有

  policyTypes:

       - Ingress

 

放行特定的网络:

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

  name: allow-all-ingress

spec:

  podSelector:

    matchLabels:

      app: myapp #放行有这个标签的pod

  ingress:

  - from:

    - ipBlock:

        cidr: 10.244.0.0/16

        except: #指定拒绝特定的网络

        - 10.244.1.2/32  

    ports: #指定放行的端口

    - protocol: TCP

      port: 80

 

 

----------------------------------------------------------------------------------------------------------

 

Node亲和性:

[root@master ~]# kubectl explain pod.spec.affinity.nodeAffinity

preferredDuringSchedulingIgnoredDuringExecution #软策略

requiredDuringSchedulingIgnoredDuringExecution #硬策略

 

节点选择器:nodeSelector, nodeName

 

节点亲和调度:nodeAffinity

 

 

Pod亲和性

[root@master ~]# kubectl explain pod.spec.affinity.podAffinity

 

 

----------------------------------------------------------------------------------------------------------

 

Taint和toleration:

节点亲和性,是pod的一种属性(偏好或硬性要求),它使pod被吸引到这一类特定的节点,taint则相反,它是节点能够排斥一类特定的pod

 

taint的effect定义对Pod排斥效果:

NoSchedule:仅影响调度过程,对现存的Pod对象不产生影响;

NoExecute:既影响调度过程,也影响现在的Pod对象;不容忍的Pod对象将被驱逐;

PreferNoSchedule:

 

 

 

 

 

 

 

资源需求与限制:

容器的资源需求,资源限制

requests:  需求,最低保障;

limits: 限制,硬限制

 

CPU:

1颗逻辑cpu

1=1000,millicores

500=0.5CPU

内存:

E, P, T, G, M, K

Ei,Pi

limits 代表上限

 

Qos: #服务质量

Guranteed: 当资源不够的时候,优先运行#同时设置CPU和内存的requests和limit

cpu.limits = cpu.requests

memory.limits = memory.request      #当条件满足时,自动归类为    guranteed

Burstable: #至少有一个容器设置CPU或内存资源的requests属性

BestEffort:  #没有任何一个容器设置了requests或limit属性;最低优先级

#当pod资源不够时,自动杀死BestEffort属性的容器

 

 

 

----------------------------------------------------------------------------------------------------------

 

 

 

Kubectl  top:

 

Heapster 收集各种指标数据,存到InfluxDB里在由Grafana图形化展示出来

 

部署:

在git上搜索heapster

https://github.com/kubernetes-retired/heapster/tree/master/deploy/kube-config #部署方法

 

这里先部署了infuexDB

[root@master ~]# wget https://raw.githubusercontent.com/kubernetes-retired/heapster/master/deploy/kube-config/influxdb/influxdb.yaml #把yaml文件wget下来

spec: 修改版本为apps/v1

  replicas: 1

  selector: #添加标签这4行

    matchLabels:

task: monitoring

     k8s-app: influxdb

  因谷歌网络限制问题,国内的K8ser大多数在学习Kubernetes过程中因为镜像下载失败问题间接地产生些许失落感,笔者也因此脑壳疼,故翻阅资料得到以下解决方式:

  在应用yaml文件创建资源时,将文件中镜像地址进行内容替换即可:

  将k8s.gcr.io替换为

  registry.cn-hangzhou.aliyuncs.com/google_containers

  或者

  registry.aliyuncs.com/google_containers

  或者

  mirrorgooglecontainers

 

然后部署heapster:

https://github.com/kubernetes-retired/heapster/tree/master/deploy/kube-config/influxdb

 

Wget https://raw.githubusercontent.com/kubernetes-retired/heapster/master/deploy/kube-config/influxdb/heapster.yaml

[root@master ~]# vim heapster.yaml #群组改成apps/v1 貌似不改也没关系,加一个标签

spec:

  replicas: 1

  selector:

    matchlabels:

      task: monitoring

      k8s-app: heapster

 

部署grafana:

[root@master ~]# wget https://raw.githubusercontent.com/kubernetes-retired/heapster/master/deploy/kube-config/influxdb/grafana.yaml

 [root@master ~]# vim grafana.yaml #跟上面一样修改版本,添加标签,如果有需要还可以添加一个nodePort 暴露在公网上

然后查看grafana的svc 浏览

 

如何导入导出面板可以参考:https://blog.csdn.net/gx_1_11_real/article/details/85161491

----------------------------------------------------------------------------------------------------------

 

Helm:

核心术语:

Chart:一个helm程序包;

Repository:Charts仓库,https/http服务器;

Release:特定的Chart部署于目标集群上的一个实例;

Chart -> Config -> Release

程序架构:

helm:客户端,管理本地的Chart仓库,管理Chart, 与Tiller服务器交互,发送Chart,实例安装、查询、卸载等 操作

Tiller:服务端,接收helm发来的Charts与Config,合并生成relase;

 

安装步骤:

现在git上找到相应的helm包,下载下来

地址:https://github.com/helm/helm/releases

解压下载的文件:

[root@master linux-386]# tar -xf tar -xf helm-v2.9.1-linux-amd64.tar.gz

#建议使用旧版本的,要不然会有很多莫名其妙的错误

把helm文件直接mv到/usr/bin 就可以直接使用

 

因为helm运行要使用管理员权限所以还要绑定cluster-admin集群角色上:

RBAC示例:

https://github.com/helm/helm/blob/master/docs/rbac.md

把示例里的yaml文件复制下来,使用apply部署

 

helm init --service-account tiller --upgrade -i registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.9.1 --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts

#因为网络问题,这里使用阿里云的helm镜像

[root@master helm]# kubectl get pods -n kube-system #查看pod是否启动

[root@master helm]# helm version #查看helm和tiller版本

 

[root@master helm]# helm repo update

[root@master helm]# helm repo list #查看可用的正在使用的仓库

官方可用的chart列表:

https://hub.kubeapps.com/

Stable代表稳定版 incubator代表测试版,最好还是使用稳定版

 

示例:

部署一个memcache:

[root@master ~]# helm search stable/memcachecd

[root@master ~]# helm inspect table/memcached

 

[root@master ~]# helm install --name mem1 stable/memcached

#部署完会有一个反馈信息在下面

 

[root@master ~]# helm delete mem1 #卸载

 

helm常用命令:

release管理:

install #安装

delete #删除

upgrade/rollback #更新/回滚

list #列出

history:release的历史信息;

status:获取release状态信息;

 

chart管理:

create

fetch

get

inspect

package

Verify

 

[root@master ~]# helm fetch stable/redis 下载包

[root@master redis]# tree ./

./

├── Chart.yaml #记录chart的元数据。。

├── README.md #说明

├── templates #各种模板文件

│   ├── deployment.yaml

│   ├── _helpers.tpl

│   ├── networkpolicy.yaml

│   ├── NOTES.txt

│   ├── pvc.yaml

│   ├── secrets.yaml

│   └── svc.yaml

└── values.yaml #自定义属性设置默认值

 

 

创建chart:

[root@master ~]# helm create myapp 它会自动生成配置文件

[root@master ~]# tree myapp/

myapp/

├── charts

├── Chart.yaml

├── templates

│   ├── deployment.yaml

│   ├── _helpers.tpl

│   ├── ingress.yaml

│   ├── NOTES.txt

│   └── service.yaml

└── values.yaml

修改完yaml文件后使用

[root@master redis]# helm lint ../redis #语法检测

 

 

ElK: #类似于ELK   

 

 

E: elasticsearch 和kibana版本一定要一致,错一个小版本号都不行

L:   logstash

K:   

Fluentd 日志收集代理工具

部署ELK:

[root@master ~]#  helm repo add incubator https://kubernetes-charts-incubator.storage.googleapis.com/ #添加测试版仓库

 

[root@master ~]# helm fetch incubator/elasticsearch #下载el  chart包

[root@master ~]# tar -xf elasticsearch-1.10.2.tgz

[root@master ~]# cd elasticsearch/

 

[root@master elasticsearch]# helm install --name els2 --namespace=efk -f values.yaml incubator/elasticsearch

 

[root@master elasticsearch]# kubectl run  -it --rm  cirror-$RANDOM --image=cirros -- /bin/sh

#运行一个测试的容器

 

[root@master ~]# helm status el2 #查看入口

 

在测试的机器里:

/ # nslookup el2-elasticsearch-client.efk.svc

 

/ # curl el2-elasticsearch-client.efk.svc:9200 #访问它的端口

 

/ # curl el2-elasticsearch-client.efk.svc.cluster.local:9200/_cat #查看es库

 

部署fluentd:

[root@master mnt]# helm fetch incubator/fluentd-elasticsearch 下载对应chart

elasticsearch:

host: 'el2-elasticsearch-client.efk.svc.cluster.local' #把这里改成解析的主机名的地址

 

tolerations:

  - key: node-role.kubernetes.io/master #把这三个注释打开,可以容忍主节点的污点

   operator: Exists

   effect: NoSchedule

 

service: #如果期望通过服务的方式来访问它就把这注释打开

  type: ClusterIP

  ports:

     - name: "monitor-agent"

       port: 24231

 

[root@master fluentd-elasticsearch]# helm install --name flu1 --namespace=efk -f values.yaml incubator/fluentd-elasticsearch #进行安装

 

部署k:

]# helm fetch stable/kibana

]# tar -xf kibana-0.2.2.tgz

如果是新版本配置如下:

 

]# helm install --name kib1 --namespace=efk -f values.yaml stable/kibana

]# kubectl edit svc -n efk kib1-kibana 修改svc为NodePort

 

完成后的页面:

 

 

 

 

 

 

 

证书

证书默认路径: [root@master pki]# ls /etc/kubernetes/pki/

 

查看证书使用年限: [root@master pki]# openssl x509 -in apiserver.crt -text -noout

 

使用go语言修改kubeadm源码,修改年限

 

准备go语言环境: 首先在百度上搜索go中文社区(因为官方在谷歌,国内不方便)

百度--> go中文社区--> 下载 --> 选择linux版本

[root@master data]# wget https://studygolang.com/dl/golang/go1.13.linux-amd64.tar.gz

[root@master data]# tar -xf go1.13.linux-amd64.tar.g -C /usr/local/

export PATH=$PATH:/usr/local/go/bin       #变量

[root@master ~]# vim /etc/profile #在这里设置环境变量

export PATH=$PATH:/usr/local/go/bin #把这个贴在文件里,官网上有

[root@master ~]# source /etc/profile

[root@master ~]# go version #查看版本

go version go1.13 linux/amd64

 

[root@master data]# git clone https://github.com/kubernetes/kubernetes 克隆

[root@master data]# cd kubernetes

[root@master kubernetes]# git checkout -b remotes/origin/release-1.15.3 v1.15.3 #切换分支

cmd/kubeadm/app/util/pkiutil/pki_helpers.go #修改年限的文件(1.14版本到1.15)

[root@master kubernetes]# vim cmd/kubeadm/app/util/pkiutil/pki_helpers.go

        const duration3650d = time.Hour * 24(小时) * 365(天) *10(年) #添加,设置常量

        certTmpl := x509.Certificate{ #大约566行

                Subject: pkix.Name{

                        CommonName:   cfg.CommonName,

                        Organization: cfg.Organization,

                },

                DNSNames:     cfg.AltNames.DNSNames,

                IPAddresses:  cfg.AltNames.IPs,

                SerialNumber: serial,

                NotBefore:    caCert.NotBefore,

                NotAfter:     time.Now().Add(duration3650d).UTC() #改成刚刚的常量

:wq

[root@master kubernetes]# make WHAT=cmd/kubeadm GOFLAGS=-v 编译

不知道为什么没有成功。。。

 

 

 

高可用k8s集群构建

 

睿云

 

 

 

 

 

 

补充:

Init(容器启动之前的操作):

参考https://www.cnblogs.com/tylerzhou/p/11007430.html

 

 

 

 

registry.cn-shanghai.aliyuncs.com/mydlq/

上一篇:kubernets过滤pod标签


下一篇:07-图5 Saving James Bond - Hard Version (30 分) 被虐到哭的一道题