0%

k8s-运行应用

部署nginx服务

使用kubectl命令

kubectl run nginx-deployment --image=nginx:1.7.9 --replicas=2

使用配置文件

创建nginx.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80

kubectl apply -f nginx-deployment.yaml

配置文件中添加nginx服务配置

上面的配置文件,nginx的配置、html页面、日志在容器里,不方便修改和查看,下面设置挂载路径,将上述文件挂载到宿主机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
volumeMounts:
- name: conf
mountPath: /etc/nginx/nginx.conf
- name: confd
mountPath: /etc/nginx/conf.d
- name: log
mountPath: /var/log/nginx
- name: html
mountPath: /etc/nginx/html
tolerations:
- key: "key"
operator: "Equal"
value: "nginx"
effect: "NoSchedule"
volumes:
- name: conf
hostPath:
path: /home/work/kube/nginx/conf/nginx.conf
- name: confd
hostPath:
path: /home/work/kube/nginx/conf.d
- name: log
hostPath:
path: /home/work/kube/nginx/logs
type: Directory
- name: html
hostPath:
path: /home/work/kube/nginx/html
type: Directory

说明:

  1. 挂载的目录或文件需要先在宿主机上创建,其中nginx.conf从nginx容器中拷贝出来:docker cp {container-name}:{container-path} {host-path}

(待补充)

更新nginx应用:kubectl apply -f nginx.yaml

创建Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx
name: nginx-deployment
spec:
ports:
- port: 9000
name: nginx-service
protocol: TCP
targetPort: 80
nodePort: 31090
selector:
app: nginx
type: NodePort

说明:

  1. 将Service的9000端口映射到Pod的80端口

    image-20220407004507010
  2. nginx-svc被分配的cluster-ip 192.168.31.22 可通过该IP访问后端nginx Pod

    image-20220407004725110
  3. kubectl describe service nginx-svc 查看nginx-svc与pod的关系

    image-20220407004927642

    Endpoints列举了两个Pod的IP和端口

    进入Pod docker exec -it {container_id} /bin/bash,查看ip地址 ip addr

    image-20220407005958681
  4. Service的Cluster IP 是怎么映射到Pod IP 的?

    通过iptables的转发规则,将流量转发到Pod上,Cluster的每个节点都配置了相同的iptables规则

    iptables-save | grep nginx

    image-20220407011152220

    其中,红框中两条规则:

    • 如果Cluster内的Pod要访问nginx-svc,则允许;
    • 其他源地址访问nginx-svc,跳转到规则KUBE-SVC-HL5LMXD5JFHQZ6LN

    KUBE-SVC-HL5LMXD5JFHQZ6LN规则为:

    image-20220407011429837

    0.5的概率跳转到KUBE-SEP-RSXKIBUPEFSC7MO6

    否则跳转到KUBE-SEP-NHHTLNEICZVNVOWJ

    下面是KUBE-SEP-RSXKIBUPEFSC7MO6KUBE-SEP-NHHTLNEICZVNVOWJ的转发规则,即转发到后端Pod

    image-20220407011738843

    综上:iptables将访问Service的流量转发到后端Pod,并使用类似轮询的负载均衡策略

  5. 只有集群内部的节点可以访问Service Cluster IP,比如在集群中,有服务A与B,A需要访问B,可以通过A的Service Cluster IP,但是这个IP是随机分配的,如果Service A销毁重建,B需要更改配置,很不方便

集群内访问nginx服务

通过Service的Cluster IP
通过DNS访问
image-20220407013135487

当有新的Service创建,coredns会添加该Service的DNS记录,Cluster中的Pod可以通过{serviceName}.{namespace}访问Service

如:在一个临时的Pod中通过DNS访问nginx Service

kubectl run busybox --rm -it --image=busybox /bin/sh

wget {serviceName}.{namespace}:{servicePort}

image-20220407014230058

由于namespace为default,故可以省略;其他namespace不可省略

image-20220407014908696

nginx-svc.default.svc.cluster.local为完整域名

这样,服务B访问A,通过A的serviceName就可以了,即使重新创建A的Service,也不需要修改B的配置

集群外部访问nginx服务

外部用户如何访问nginx?

NodePort

Service绑定Cluster节点的静态端口对外提供服务,Cluster外部通过{NodeIP}:{NodePort},如master:31090node1:31090

如何将{NodeIP}:{NodePort}映射到Pod的?

image-20220407020203297

使用iptabels,上面两条规则:当访问31090端口的请求转发到规则KUBE-SVC-HL5LMXD5JFHQZ6LN

image-20220407020414875

KUBE-SVC-HL5LMXD5JFHQZ6LN 对Pod进行负载均衡

相关指令

动作 指令
查看nginx的pods kubectl get pods -n namespace
查看发布的deployment详情 kubectl describe deployment nginx -n namespace
查看pod详情 kubectl describe pod {pod_name} -n namespace
删除pod kubectl delete -n default pod nginx-deployment
查询服务列表 kubectl get services -n namespace
查询服务详情 kubectl describe service {deployment-name} -n namespace
删除一个service服务 kubectl delete services {deployment-name} -n namespace

存在问题

  1. 挂载的路径和文件需要提前创建在宿主机,集群下无法确定在哪台机器上部署,不方便提前创建,如何解决?
  2. 访问集群中的任意节点都按照相同的iptables进行转发到某个Pod,即访问每个节点都有负载均衡的效果,那外部域名应该绑定哪个节点ip呢?还是通过一个nginx对Cluster中的节点做分发(防止节点挂机,不是做负载均衡)