一.Deployment 资源详解
如果Pod出现故障,对应的服务也会挂掉,所以Kubernetes提供了一个Deployment的概念 ,目的是让Kubernetes去管理一组Pod的副本,也就是副本集 ,这样就能够保证一定数量的副本一直可用,不会因为某一个Pod挂掉导致整个服务挂掉。
Deployment 还负责在 Pod 定义发生变化时,对每个副本进行滚动更新(Rolling Update)。
x 使用yaml创建Deployment
k8s deployment资源创建流程:
1. 用户通过 kubectl 创建 Deployment。
2. Deployment 创建 ReplicaSet。
3. ReplicaSet 创建 Pod。
对象的命名方式是:子对象的名字 = 父对象名字 + 随机字符串或数字
Deployment是一个定义及管理多副本应用(即多个副本 Pod)的新一代对象,与Replication Controller相比,它提供了更加完善的功能,使用起来更加简单方便。
1.1 deployment 实例
例1:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
例2:在上面yaml的基础上添加了volume
[root@kube-master sa]# cat deployment.yaml
apiVersion: apps/v1 #注意版本号
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector: #属性,选择器
matchLabels:
app: nginx
replicas: 2 #管理的副本个数
template: #模板属性
metadata: #对pod的描述
labels:
app: nginx
spec:
volumes: #定义共享卷
- name: nginx-vol
emptyDir: {}
containers:
- name: nginx
image: daocloud.io/library/nginx
ports:
- containerPort: 80
volumeMounts: #定义挂载卷
- mountPath: "/usr/share/nginx/html"
name: nginx-vol
1.2 文件说明
#创建Deployment:
#将上述的YAML文件保存为deployment.yaml,然后创建Deployment:
[root@kube-master prome]# kubectl apply -f deployment.yaml
deployment.apps/nginx-deployment created
# 检查Deployment的列表:启动之后需要创建时间比较长
# 通过 kubectl get 命令检查这个 YAML 运行起来的状态:
[root@kube-master prome]# kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 2/2 2 2 2m22s
[root@kube-master prome]# kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
nginx-deployment-59c4b86474-2llrt 1/1 Running 0 2m51s
nginx-deployment-59c4b86474-n2r2m 1/1 Running 0 2m51s
# 在这里加上了一个 -l 参数,即获取所有匹配 app: nginx 标签的 Pod。需要注意的是,在命令行中,所有 key-value 格式的参数,都使用"="而非":"表示。
# 删除Deployment:
[root@kube-master ~]# kubectl delete deployments nginx-deployment
deployment "nginx-deployment" deleted
#或者
[root@kube-master ~]# kubectl delete -f deployment.yaml
1.3 deployment可用字段
replicas: 1 # 声明副本数目
revisionHistoryLimit: 3 # 保留历史版本
selector: # 选择器
二.Service 服务
k8s 内部域名访问方式 ..svc.cluster.local
2.1 创建service
# 1.创建一个depl
[root@kub-k8s-master prome]# vim nginx-depl.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: dep01
spec:
selector:
matchLabels:
app: web
replicas: 2
template:
metadata:
labels:
app: web
spec:
containers:
- name: testnginx9
image: daocloud.io/library/nginx
ports:
- containerPort: 80
[root@kub-k8s-master prome]# kubectl apply -f nginx-depl.yml
deployment.apps/nginx-deployment created
#2. 创建service并且以nodePort的方式暴露端口给外网:
[root@kub-k8s-master prome]# vim nginx_svc.yaml
apiVersion: v1
kind: Service
metadata:
name: mysvc
spec:
type: NodePort #类型
ports:
- port: 8080
nodePort: 30001
targetPort: 80
selector: #选择器
app: web
[root@kub-k8s-master prome]# kubectl apply -f nginx_svc.yaml
service/mysvc created
# 3.测试
[root@kub-k8s-master prome]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d18h
mysvc NodePort 10.100.166.208 <none> 8080:30001/TCP 21s
2.2 页面请求测试
2.3 pod内部请求测试
# 进入docker容器
[root@kube-master sa]# kubectl exec -it dep01-694c5dbcd-ccdsv /bin/bash
# 请求
root@dep01-694c5dbcd-ccdsv:/# curl mysvc.default.svc.cluster.local:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
2.4 端口解析
# 解析
port
port是暴露在cluster ip上的端口,port提供了集群内部客户端访问service的入口,即clusterIP:port。nodeport
nodePort 提供了集群外部客户端访问 Service 的一种方式,nodePort 提供了集群外部客户端访问 Service 的端口,通过 nodeIP:nodePort 提供了外部流量访问k8s集群中service的入口。targetPort
targetPort是pod的端口,从port和nodePort来的流量经过kube-proxy流入到后端pod的targetPort上,最后进入容器。containerPort
containerPort是pod内部容器的端口,targetPort映射到containerPort。
2.5 kube-proxy 使用ipvs
[root@kube-master ~]# kubectl get configmap kube-proxy -n kube-system -o yaml > kube-proxy-configmap.yaml
[root@kube-master ~]# sed -i 's/mode: ""/mode: "ipvs"/' kube-proxy-configmap.yaml
[root@kube-master ~]# kubectl apply -f kube-proxy-configmap.yaml
[root@kube-master ~]# rm -f kube-proxy-configmap.yaml
[root@kube-master ~]# kubectl get pod -n kube-system | grep kube-proxy | awk '{system("kubectl delete pod "$1" -n kube-system")}'
后续请求时,可以发现已经通过了算法进行调度
[root@kube-master ~]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 172.17.0.1:30001 rr
-> 10.244.1.34:80 Masq 1 0 0
-> 10.244.2.31:80 Masq 1 0 0
TCP 192.168.96.143:30001 rr
-> 10.244.1.34:80 Masq 1 0 12
-> 10.244.2.31:80 Masq 1 0 12
三.k8s服务暴露
3.1 ClusterIP
此类型会提供一个集群内部的虚拟IP(与Pod不在同一网段),以供集群内部的pod之间通信使用。ClusterIP也是Kubernetes service的默认类型。
3.2 NodePort
外网client--->nodeIP+nodePort--->podIP+PodPort
为每个节点暴露一个端口,通过nodeip + nodeport可以访问这个服务,同时服务依然会有cluster类型的ip+port。内部通过clusterip方式访问,外部通过nodeport方式访问。
3.3 loadbalance
LoadBalancer在NodePort基础上,K8S可以请求底层云平台创建一个负载均衡器,将每个Node作为后端,进行服务分发。
3.4 Ingress
Ingress是一种HTTP方式的路由转发机制,为K8S服务配置HTTP负载均衡器,通常会将服务暴露给K8S群集外的客户端。
四.Ingress 暴露服务
> 要理解ingress,需要区分两个概念,ingress和ingress-controller:
> ingress对象:
> 指的是k8s中的一个api对象,一般用yaml配置。作用是定义请求如何转发到service的规则,可以理解为配置模板。> ingress-controller:
> 具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发。> 简单来说,ingress-controller才是负责具体转发的组件,通过各种方式将它暴露在集群入口,外部对集群的请求流量会先到ingress-controller,而ingress对象是用来告诉ingress-controller该如何转发请求,比如哪些域名哪些path要转发到哪些服务等等。
> service 的表现形式为IP:PORT,即工作在第四层传输层(TCP/IP层),对于不同的URL地址经常对应用不同的后端服务或者虚拟服务器,这些应用层的转发机制仅通过kubernetes的service机制是无法实现的,这种情况我么可以使用ingress策略定义和一个具体的ingress Controller.> Ingress提供七层负载均衡能力,可以通过 Ingress 配置提供外部可访问的 URL、负载均衡、SSL、基于名称的虚拟主机等。作为集群流量接入层,Ingress 的高可靠性显得尤为重要。
4.1 ingress详解
这个负载均衡是基于nginx七层反向代理来实现的,ingress工作原理如下图:
外部客户端通过访问负载均衡器,然后调度到service上,然后在调度到IngressController,IngressController通过Ingress规则(域名或虚拟主机)访问到后端pod,而在Ingress规则当中对应的主机是由service分组来设定的,可以看到,这幅图有2种service,最上面的service是用来对外提供服务的,而下面2个service仅仅是用来分pod组的
Kubernetes 并没有自带 Ingress Controller,实际上ingress-controller只是一个统称,具体实现有多种,需要自己单独安装,目前,由k8s维护的ingress-controller只有google云的GCE与ingress-nginx两个,常用的是 Ingress-nginx Controller.
Ingress 一般由三个组件组成:
1. Nginx 反向代理负载均衡器
2. Ingress Controller 可以理解为控制器,它通过不断的跟 Kubernetes API 交互,实时获取后端 Service、Pod 等的变化,比如新增、删除等,然后结合 Ingress 定义的规则生成配置,然后动态更新上边的 Nginx 负载均衡器,并刷新使配置生效,来达到服务自动发现的作用。
3. Ingress 则是定义规则,通过它定义某个域名的请求过来之后转发到集群中指定的 Service。它可以通过 Yaml 文件定义,可以给一个或多个 Service 定义一个或多个 Ingress 规则。
4.2 如何创建 Ingress 资源
Ingress 中的spec字段是Ingress资源的核心组成部分,主要包含以下3个字段:
rules:用于定义当前Ingress资源的转发规则列表;由rules定义规则,或没有匹配到规则时,所有的流量会转发到由backend定义的默认后端。
backend:默认的后端,用于服务那些没有匹配到任何规则的请求;定义Ingress资源时,必须要定义backend或rules两者之一,该字段用于让负载均衡器指定一个全局默认的后端。
tls:TLS配置,目前仅支持通过默认端口443提供服务,如果要配置指定的列表成员指向不同的主机,则需要通过SNI TLS扩展机制来支持该功能。
4.3 部署 Ingress 控制器(Nginx)
4.3.1 下载ingress controller
[root@k8s-master ~]# cd /mnt/
[root@k8s-master mnt]# wget https://codeload.github.com/kubernetes/ingress-nginx/tar.gz/refs/tags/controller-v1.3.1
[root@k8s-master mnt]# tar xf ingress-nginx-controller-v1.3.1.tar.gz
[root@k8s-master mnt]# cd ingress-nginx-controller-v1.3.1/deploy/static/provider/cloud
[root@k8s-master cloud]# ls
deploy.yaml kustomization.yaml
[root@k8s-master cloud]# cd
[root@k8s-master ~]# vim deploy.yaml #修改配置文件
找到已下apiserver的版本:
# 390行修改
kind: DaemonSet #将原来的Deployment修改为DaemonSet
# 415行下边添加
hostNetwork: true #添加此配置
需要修改的地方:
kind: DaemonSet:
官方原始文件使用的是deployment,replicate 为 1,这样将会在某一台节点上启动对应的nginx-ingress-controller pod。外部流量访问至该节点,由该节点负载分担至内部的service。测试环境考虑防止单点故障,改为DaemonSet然后删掉replicate ,配合亲和性部署在制定节点上启动nginx-ingress-controller pod,确保有多个节点启动nginx-ingress-controller pod,后续将这些节点加入到外部硬件负载均衡组实现高可用性。
hostNetwork: true:
添加该字段,暴露nginx-ingress-controller pod的服务端口(80)
4.3.2 创建ingress-controller
[root@k8s-master ~]# kubectl apply -f deploy.yaml
查看ingress-controller资源
[root@k8s-master ~]# kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-s8vnl 1/1 Running 0 98m
nginx-ingress-controller-ztxz4 1/1 Running 0 97m
[root@k8s-master cloud]# kubectl get ingressclass
NAME CONTROLLER PARAMETERS AGE
nginx k8s.io/ingress-nginx <none> 38m
测试ingress
创建两个应用和service
[root@k8s-master ~]# vim my-apache.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-apache
spec:
selector:
matchLabels:
run: my-apache
replicas: 2
template:
metadata:
labels:
run: my-apache
spec:
containers:
- name: my-apache
image: daocloud.io/library/httpd:2.4
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-apache
labels:
run: my-apache
spec:
#type: NodePort
ports:
- port: 80
targetPort: 80
#nodePort: 30002
selector:
run: my-apache
[root@k8s-master ~]# cat my-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: daocloud.io/library/nginx:1.7.9
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
#type: NodePort
ports:
- port: 80
targetPort: 80
#nodePort: 30001
selector:
run: my-nginx
创建pod和service
[root@k8s-master ~]# kubectl apply -f my-apache.yaml
[root@k8s-master ~]# kubectl apply -f my-nginx.yaml
查看资源
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
my-apache-d49c8b95c-8z8l9 1/1 Running 0 125m
my-apache-d49c8b95c-d9q5s 1/1 Running 0 125m
my-nginx-5fdc96f9b4-bmf6s 1/1 Running 0 124m
my-nginx-5fdc96f9b4-qfw8c 1/1 Running 0 124m
[root@k8s-master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 20d
my-apache NodePort 10.99.178.186 <none> 80/TCP 125m
my-nginx NodePort 10.97.171.188 <none> 80/TCP 124m
配置ingress转发文件
[root@k8s-master ~]# cat ingress-test.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules: #定义转发规则
- host: test.apache.ingress #指定域名方式
http:
paths:
- path: / #指定访问的路径
pathType: Prefix #定义路径的类型
backend: #定义转发后端的服务
service: #定义转发的service
name: my-apache
port:
number: 80
- host: test.nginx.ingress
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-nginx
port:
number: 80
[root@k8s-master ~]# kubectl apply -f ingress-test.yaml
[root@k8s-master ~]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
test-ingress <none> test.apache.ingress,test.nginx.ingress 80 119m
4.3.3 修改ingress转发类型
[root@k8s-master ~]# kubectl edit svc ingress-nginx-controller -n ingress-nginx
# 将type修改为NodePort
nginx-ingress-controller运行在node1,node2两个节点上。
如果网络中有dns服务器,在dns中把这两个域名映射到nginx-ingress-controller运行的任意一个节点上,如果没有dns服务器只能修改host文件了。
任意一个节点上操作:(客户端解析)
我这里有两个节点部署了控制器,ip分别为172.16.229.5,172.16.229.6 ,如果有多个,可以随便选。
在wind电脑设置本地解析
172.16.229.5 test.nginx.ingress
172.16.229.6 test.apache.ingress