kubernets全套笔记
阅读原文时间:2021年06月05日阅读:1

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               443/TCP   93m

myapp        ClusterIP   10.97.57.166            80/TCP    22s

nginx        ClusterIP   10.108.78.248           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               443/TCP        155m

myapp        NodePort    10.97.57.166            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/