k8s

kubernetes

Kubernetes技术已经成为了原生云技术的事实标准,它是目前基础软件领域最为热门的分布式调度和管理平台。于是,Kubernetes也几乎成了时下开发工程师和运维工程师必备的技能之一。

容器编排系统:

  • Docker Swarm
  • Apache Mesos and Marathon
  • kubernetes

k8s物理结构
master

  • API Server(数据库,实现对容器的增删改查)

    API
    UI
    CLI

  • Scheduler(watch API Server上的变动,一旦发现变动就同步变动。)

  • Controller(对比用户期望的和现有的资源状态)

  • etcd

service:

  • proxy mode: userspace/iptables/ipvs

    kube-proxy

  • service type: ClusterIP, NodePort(30000-32767之间的端口), LoadBalancer,ExternalName,

  • label selector:Pod资源,自动为每个Pod对象创建Endpoint

PV的回收策略:

  • return
  • resycle
  • delete

部署k8s测试集群

主机环境预设

安装程序包

在各节点配置docker-ce仓库

1
[root@master yum.repos.d]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

安装docker-ce

1
[root@master yum.repos.d]# yum -y install docker-ce

配置启动docker
修改docker的启动文件,在service配置段增加如下内容

1
2
3
4
5
[root@master yum.repos.d]# vi /usr/lib/systemd/system/docker.service
[Service]
Environment="HTTPS_PROXY=http://www.ik8s.io:10070" #设定访问k8s时的代理
Environment="NO_PROXY=127.0.0.0/8,192.168.34.0/32,172.18.0.0/24" #对哪些网段不使用代理
ExecStartPost=/usr/sbin/iptables -P FORWARD ACCEPT #由于docker会在启动时将FORWARD链修改为DROP,所以在启动docker后要将默认策略改为ACCEPT,以确保不影响k8s的使用。

启动docker

1
[root@master yum.repos.d]#systemctl start docker && systemctl enable docker

修改内核参数

1
2
3
[root@master yum.repos.d]# cat /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1

重载内核参数

1
2
3
[root@master yum.repos.d]# sysctl -p /etc/sysctl.d/k8s.conf 
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1

配置kubernetes的yum仓库

1
2
3
4
5
6
7
[root@master yum.repos.d]# cat k8s.repo 
[kubernetes]
name=k8s
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg

安装kubernetes

1
[root@master yum.repos.d]# yum install kubeadm kubelet

如果未关闭swap,则再启动kubernetes时必须加一个参数,禁止检查swap分区。

1
2
[root@master yum.repos.d]# cat /etc/sysconfig/kubelet 
KUBELET_EXTRA_ARGS="--fail-swap-on=false"

而后,在运行初始化命令之前先运行如下命令单独获取相关的镜像文件,然后在执行初始化命令,以便观察到镜像文件的下载过程。

1
~]# kubeadm config images pull

初始化master节点

1
~]# kubeadm init --kubernetes-version=v1.13.3 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 --ignore-preflight-errors=Swap

命令中的各选项简单说明如下:

(1) --kubernetes-version选项的版本号用于指定要部署的Kubenretes程序版本,它需要与当前的kubeadm支持的版本保持一致;
(2) --pod-network-cidr选项用于指定分Pod分配使用的网络地址,它通常应该与要部署使用的网络插件(例如flannel、calico等)的默认设定保持一致,10.244.0.0/16是flannel默认使用的网络;
(3) --service-cidr用于指定为Service分配使用的网络地址,它由kubernetes管理,默认即为10.96.0.0/12;
(4) 最后一个选项“--ignore-preflight-errors=Swap”仅应该在未禁用Swap设备的状态下使用。

如果是一个普通用户使用k8s集群,则需要执行如下步骤

1
2
3
~]#  mkdir -p $HOME/.kube
~]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
~]# sudo chown $(id -u):$(id -g) $HOME/.kube/config

如果是root用户,则直接再加目录下执行如下操作即可

1
2
~]#mkdir -p root/.kube
~]# cp -i /etc/kubernetes/admin.conf root/.kube/config

添加flannel网络附件

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

使用如下命令确认其输出结果中Pod的状态为”Running”

1
2
3
~]# kubectl get pods -n kube-system -l app=flannel
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-amd64-wscnz 1/1 Running 0 14m

验证master节点已经就绪

1
2
3
 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 53m v1.13.3

至此,kubernetes就能已经搭建完成。接下来,向该集群中加入节点:

在需要加入的节点上安装kubeadm kubectl kubelet,然后使用如下命令将节点加入到该集群中:

1
~]# kubeadm join 172.18.139.207:6443 --token 5w02cc.eivi4xb8885qnb8h --discovery-token-ca-cert-hash sha256:569ce592569c88a322c701458d70130d66ae92bbe24cf97900754beb0ff4ac1a --ignore-preflight-errors=Swap

node加入集群报错:

1
[discovery] Failed to request cluster info, will try again: [Get https://192

解决方案:
次报错是由于node和master的时间不一致导致的,需要使用ntp做时间同步。

获取集群状态信息

1
[root@master ~]# kubectl cluster-info

其中一个节点在执行过程中报如下错误

1
2
3
4
[root@node03 ~]# sysctl -p /etc/sysctl.d/k8s.conf 
net.ipv4.ip_forward = 1
sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-ip6tables: No such file or directory
sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-iptables: No such file or directory

解决办法为,加载相应的内核模块

1
[root@node03 ~]# modprobe br_netfilter

之后就可以正常修改内核参数。

从集群中移除节点

如果运行过程中需要从正常运行的集群中移除节点,则执行以下步骤:

1
2
~]# kubectl drain NODE_ID --delete-local-data --force --ignore-daemonsets
~]# kubectl delete node NODE_ID

然后再需要删除的节点上执行如下命令重置系统状态便可完成移除操作

1
~]# kubeadm reset

重新生成用于节点加入几群的认证命令

获取集群上存在的认证令牌

1
~]# kubeadm token list

生成用于验证CA的哈希值(discovery-token-ca-cert-hash)的命令如下:

1
~]# openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'

然后,将上述两个命令生成的结果合称为如下格式的kubeadm join命令即可用于让node加入急群众,其中TOKEN为上面第一个命令看到的token,HASH为第二条命令生成的HASH

1
~]# kubeadm join master-ip:port --token TOKEN --discovery-token-ca-cert-hash HASH

管理kubernetes集群

kubectl命令常用操作示例

创建资源对象

创建名为nginx-deploy的Deployment控制器资源对象

1
2
3
[root@master ~]# kubectl run nginx-deploy --image=nginx:1.12 --replicas=2
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/nginx-deploy created

创建名为nginx-svc的Service资源对象

1
[root@master ~]# kubectl expose deployment/nginx-deploy --name=nginx-svc --port=80

pod地址:
service:nodeport
hostport
hostnetwork

查看资源对象

1
2
~]# kubectl get namespace #列出系统上所有的namespace资源对象
~]# [root@master ~]# kubectl get pods -l k8s-app -o wide -n kube-system #列出kube-system名称空间下拥有k8s-app标签名称的所有pod对象

打印资源对象的详细信息

每个资源对象都包含着用户期望的状态(spec)和现有的实际状态(status)两种状态信息,”kubectl get -o {yaml|json}” 或 “kubectl describe”命令都能打印出指定资源的详细信息.

1
[root@master ~]# kubectl get pods -l component=kube-apiserver -o yaml -n kube-system

打印容器中的日志信息

命令格式:

kubectl logs [-f] [-p] (POD|TYPE/NAME) [-c CONTAINER] [options] 
1
[root@master ~]# kubectl logs kube-apiserver-master.ilinux.io -n kube-system

在容器中执行命令

1
[root@master ~]# kubectl exec kube-apiserver-master.ilinux.io -n kube-system -- ps

如果pod对象中存在多个容器,则需要以-c选项指定容器后再运行。

删除资源对象

删除单个对像,如果对象受控于控制器,则删除之后其控制器可能会重建出类似的对象。

1
[root@master ~]# kubectl delete svc nginx-svc

删除拥有某一标签的所有对象

1
kubectl delete pods -l app=monitor -n kube-system

删除指定名称空间的所有某类对象,可以使用kbectl delete TYPE –all -n NS,例如,删除kube-public名称空间中的所有pod对象。

1
kubectl delete pods --all -n kube-public

另外,有些资源类型(如pod),支持优雅删除的机制,它们有着默认的删除宽限期,不过,用户可以在命令中使用–grace-period或–now选项来覆盖默认的宽限期。

命令式容器应用编排

k8s集群网络:

  • node network:与外部网络接口
  • service network:
  • pod network:内部网络

pod相关操作

pod标签相关的操作

基于配置文件生成pod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@master basic]# cat pod-demo-2.yaml 
apiVersion: v1
kind: Pod
metadata:
name: pod-demo
namespace: prod
labels:
app: pod-demo
rel: stable
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
- name: bbox
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c","sleep 86400"]
[root@master basic]# kubectl apply -f pod-demo-2.yaml

通过命令为为pod打标签

1
[root@master basic]# kubectl label pods pod-demo -n prod tier=backend --overwrite

修改pod已有标签的值

1
[root@master basic]# kubectl label pods pod-demo -n prod tier=backend --overwrite

删除pod的某个标签

1
2
3
4
5
6
7
8
[root@master basic]# kubectl get pods -n prod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
pod-demo 0/2 Terminating 0 130m app=pod-demo,rel=stable,tier=backend
[root@master basic]# kubectl label pods pod-demo -n prod rel-
pod/pod-demo labeled
[root@master basic]# kubectl get pods -n prod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
pod-demo 0/2 Terminating 0 130m app=pod-demo,tier=backend

筛选具有某个特定标签的pod

1
[root@master basic]# kubectl get pods -l run(!)=myapp

筛选具有一组标签的某一个标签的pod

1
[root@master basic]# kubectl get pods --show-labels -l "run in (myapp,ngx-dep)"

pod资源注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@master basic]# cat pod-demo-2.yaml 
apiVersion: v1
kind: Pod
metadata:
name: pod-demo
namespace: prod
labels:
app: pod-demo
rel: stable
annotations:
ik8s.io/project: hello
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
- name: bbox
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c","sleep 86400"]

livenessProbe

容器健康状态检查,一旦检查到不健康,会自动重启容器。配置spec上下文

1
2
3
4
5
6
7
8
livenessProbe:
httpGet:
path: /healthz
port: http
scheme: HTTP
periodSeconds: 2
failureThreshold: 2
initialDelaySeconds: 3

readinessProbe

容器就绪状态检测,没有重启容器的权利。

pod对象的相位

pod对象纵使应该处于其生命进程中以下几个相位(phase)之一

  • pending:API server创建了pod资源对象并已存入etcd中,但它尚未被调度完成,或仍处于从仓库中下载镜像的过程中。
  • running:pod已经被调度至某节点,并且所有的容器都已经被kubelet创建完成
  • succeeded:pod中的所有容器都已经成功终止并且不会被重启
  • failed:所有容器都已经终止,但至少有一个容器终止失败,即容器返回了非0值的退出状态或已经被系统终止。
  • unknown:API server无法正常获取到pod对象的状态信息,通常是由于其无法与所在工作节点的kubelet通信所致。

容器的重启策略

pod对象因容器程序崩溃或容器申请超出限制的资源等原因都可能导致其被终止,此时是否应该重建此容器取决于其重启策略。

  • Always:但凡pod对象终止就将其重启,此为默认设定。
  • OnFailure:仅在pod对象出现错误时方才将其重启。
  • Never:从不重启。

资源需求及资源限制

容器的计算资源配额

  • CPU属于可压缩(compressible)型资源,即资源额度可按需收缩,而内存(当前)则是不可压缩型资源,对其执行收缩操作可能会导致某种程度的问题

  • CPU资源的计量方式

    一个核心相当于1000个微核心,即1=1000m,0.5=500m

  • 内存资源的计量方式

    默认单位为字节,也可以使用E,P,T,G,M和K后缀单位。

pod服务质量类别

根据pod对象的requests和limits属性,kubernetes把pod对象归类到besteffort、burstable和guaranteed三个服务质量类别(Quality of Service,QoS)下

  • guaranteed,每个容器都为CPU资源设置了具有相同值的requests和limits属性,以及每个容器都为CPU资源设置了具有想通知的requests和limits属性的pod资源会自动归属此类别,这类pod资源具有最高优先级
  • burstable:至少有一个容器设置了CPU或内存资源的requests属性,但不满足guaranteed类别要求的pod资源自动归属此类别。
  • besteffort:未为任何一个容器设置requests或limits属性的pod资源自动归属此类别。

Pod控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@master chapter5]# cat rs-example.yaml 
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myapp-rs
namespace: prod
spec:
replicas: 2
selector:
matchLabels:
app: myapp-pod
template:
metadata:
labels:
app: myapp-pod
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80

修改pod数量的命令:

1
[root@master chapter5]# kubectl scale --replicas=2 rs myapp-rs -n prod

升级pod中容器使用的镜像的方法:
修改rs配置文件指定image版本