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
前提:
- 基于主机名通信: /etc/hosts
- 时间同步 要不然会出一大推乱七八糟的报错
- 关闭firewall和iptables.service
OS: Centos 7.3.1611 Rxtras仓库中
安装配置步骤:
- Etcd cluster, 近master节点
- Flannel,集群的所有节点
- 配置k8s的master: 仅master节点
Kubernetes-master
启动的服务:
Kube-apiserver, kube-scheduler, kube-controller-manager
- 配置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控制器
- 稳定且唯一的网络标识符
- 稳定且持久的存储
- 有序,平滑地部署和扩展
- 有序的滚动更新
一个典型的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) [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集群的管理方式:
- 命令式: create, run, expose, delete。。。
- 命令式配置文件: 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
[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列表:
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/