Kubernetes-Service 网络资源

发布时间 2023-10-08 15:58:39作者: 普里莫

Kubernetes-Service 网络资源

nginx-php-mysql 分开部署示例

apiVersion: "v1"
kind: "Pod"
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  volumes:
  - name: nginx-data
    hostPath:
      path: /data/nginx
  - name: nginx-code
    hostPath:
      path: /data/code
  containers:
  - name: nginx-container
    image: nginx:alpine
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: nginx-data
      mountPath: /etc/nginx/conf.d/
    - name: nginx-code
      mountPath: /code
---
apiVersion: "v1"
kind: "Pod"
metadata:
  name: php-pod
spec:
  volumes:
  - name: php-data
    hostPath:
      path: /data/php
  containers:
  - name: php-container
    image: php:7.4.33-fpm
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: php-data
      mountPath: /usr/local/etc/php-fpm.d/
---
apiVersion: "v1"
kind: "Pod"
metadata:
  name: mysql-pod
spec:
  volumes:
  - name: mysql-data
    hostPath:
      path: /data/mysql
  containers:
  - name: mysql-container
    image: mysql:5.7
    imagePullPolicy: IfNotPresent
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: '123'
    - name: MYSQL_DATABASE
      value: 'wordpress'
    - name: MYSQL_USER
      value: 'wp'
    - name: MYSQL_PASSWORD
      value: '123'
    volumeMounts:
    - name: mysql-data
      mountPath: /var/lib/mysql
 
## 结论 
nginx访问php ip要写死
nginx与php需要同时部署相同的资源才能起一个服务

k8s 的三种 IP

Nodeport
节点对外提供访问的IP
 
ClusterIP
用来动态发现和负载均衡POD的IP
 
PodIP
提供pod使用的IP
 
## Service提供四种资源:
ExternalName
ClusterIP
NodePort
LoadBalancer

image-20230925094919087

nginx 示例(ClusterIP)

Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-db
  labels:
    app: nginx-labels
spec:
  replicas: 6
  selector:
    matchLabels:
      app: nginx-labels
  template:
    metadata:
      labels:
        app: nginx-labels
    spec:
      containers:
      - name: nginx-db
        image: nginx:alpine
        imagePullPolicy: IfNotPresent

ClusterIP

kind: Service
apiVersion: v1
metadata:
  name: nginx-svc
spec:
  selector:
    # 寻找的是pod的标签而不是控制器的标签 
    app: nginx-labels
  type: ClusterIP
  ports:
  - name: nginx-port
    port: 80
    targetPort: 80
    protocol: TCP
 
# 查找service
[root@master-1 tmp]# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.1.0.1      <none>        443/TCP   6d21h
nginx-svc    ClusterIP   10.1.160.35   <none>        80/TCP    3d16h
 
# 查找service中nginx-svc的详细信息
[root@master-1 tmp]# kubectl describe svc nginx-svc 
Name:              nginx-svc
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx-labels
Type:              ClusterIP
IP:                10.1.160.35
Port:              nginx-port  80/TCP
TargetPort:        80/TCP
Endpoints:         10.2.1.51:80,10.2.1.52:80,10.2.2.72:80 + 3 more...
Session Affinity:  None
Events:            <none>
 
# 查看clusterip的nginx内容
[root@master-1 tmp]# curl 10.1.160.35
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
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>

mysql 示例(ClusterIP)

Deployment

# 编写资源清单
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-db
  labels:
    app: mysql-db
spec:
  replicas: 1
  selector:
    matchLabels:
      mysql: pod
  template:
    metadata:
      labels:
        mysql: pod
    spec:
      containers:
      - name: mysql-pod
        image: mysql:5.7
        imagePullPolicy: IfNotPresent
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "123"
        - name: MYSQL_DATABASE
          value: wordpress
        - name: MYSQL_USER
          value: wp
        - name: MYSQL_PASSWORD
          value: "123"
 
# 启动
[root@master-1 tmp]# kubectl apply -f mysql-dp.yml 
deployment.apps/mysql-db created

service

# 编写资源清单
kind: Service
apiVersion: v1
metadata:
  name: mysql-svc
spec:
  selector:
    mysql: pod
  type: ClusterIP
  ports:
  - name: mysql-port
    port: 3306
    targetPort: 3306
    protocol: TCP
 
# 启动
[root@master-1 tmp]# kubectl apply -f mysql-svc.yml 
service/mysql-svc created
 
# 查找mysql-svc的详细信息
[root@master-1 tmp]# kubectl describe svc mysql-svc 
Name:              mysql-svc
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          mysql=pod
Type:              ClusterIP
IP:                10.1.105.7
Port:              nginx-port  3306/TCP
TargetPort:        3306/TCP
Endpoints:         10.2.2.76:3306
Session Affinity:  None
Events:            <none>
 
# 尝试连接
[root@node-2 ~]# mysql -uroot -p123 -h10.1.105.7
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.36 MySQL Community Server (GPL)
 
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
 
MySQL [(none)]> 

SVC 的通信流程

1)启动任何 pod 时,每个 pod 都会配置 nameserver coredns-svc

root@mysql-db-5bd9b8fbf4-2g4vj:/# cat /etc/resolv.conf 
nameserver 10.1.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

2)所有 pod 通过 svc 找到 coredns 服务器

[root@master-1 tmp]# kubectl get svc -n kube-system
NAME             TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
kube-dns         ClusterIP   10.1.0.10    <none>        53/UDP,53/TCP,9153/TCP   7d3h
 
[root@master-1 tmp]# kubectl describe svc -n kube-system kube-dns
Name:              kube-dns
Namespace:         kube-system
Labels:            k8s-app=kube-dns
                   kubernetes.io/cluster-service=true
                   kubernetes.io/name=KubeDNS
Annotations:       prometheus.io/port: 9153
                   prometheus.io/scrape: true
Selector:          k8s-app=kube-dns
Type:              ClusterIP
IP:                10.1.0.10
Port:              dns  53/UDP
TargetPort:        53/UDP
Endpoints:         10.2.0.2:53,10.2.2.2:53
Port:              dns-tcp  53/TCP
TargetPort:        53/TCP
Endpoints:         10.2.0.2:53,10.2.2.2:53
Port:              metrics  9153/TCP
TargetPort:        9153/TCP
Endpoints:         10.2.0.2:9153,10.2.2.2:9153
Session Affinity:  None
Events:            <none>

3)当启动 svc 资源时,会建 svc 的名字和 svc 的 ip 地址,在 coredns 中解析

[root@master-1 tmp]# kubectl describe svc mysql-svc 
Name:              mysql-svc
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          mysql=pod
Type:              ClusterIP
IP:                10.1.105.7
Port:              nginx-port  3306/TCP
TargetPort:        3306/TCP
Endpoints:         10.2.2.76:3306
Session Affinity:  None
Events:            <none>
 
任何pod只要ping svc的名称就可以进行通信

image-20230925161023879

nginx 示例(NodePort)

存在问题:

1)kubeadm 中针对 NodePort 设置了端口范围:30000-32767

2)在 nodeport 中的端口映射,是四层,防火墙 iptables 转发的

3)一个 nginx pod 只能起一个网站,起多个不认识域名

# 编写资源清单
kind: Service
apiVersion: v1
metadata:
  name: nginx-svc
spec:
  selector:
    app: nginx-labels
  type: NodePort
  ports:
  - name: nginx-port
    port: 80
    targetPort: 80
    protocol: TCP
    nodePort: 30002
 
# 启动
[root@master-1 tmp]# kubectl apply -f 11.yml 
service/nginx-svc configured

image-20230925105742343

解决方法:

只写 ClusterIP,不使用 NodePort

在企业中,使用 Ingress

NodePort 缺陷

\1. 没有 ingress 之前,pod 对外提供服务只能通过 NodeIP:NodePort 的形式,但是这种形式有缺点,一个节点上的 PORT 不能重复利用。比如某个服务占用了 80,那么其他服务就不能在用这个端口了。

2.NodePort 是 4 层代理,不能解析 7 层的 http,不能通过域名区分流量

\3. 为了解决这个问题,我们需要用到资源控制器叫 Ingress,作用就是提供一个统一的访问入口。工作在 7 层

\4. 虽然我们可以使用 nginx/haproxy 来实现类似的效果,但是传统部署不能动态的发现我们新创建的资源,必须手动修改配置文件并重启。

\5. 适用于 k8s 的 ingress 控制器主流的有 nginx-ingress、traefik、haproxy-ingress

nginx-Ingress

image-20230925161458349

部署 nginx-ingress

# 拉取镜像
[root@node-1 ~]# docker pull nginx/nginx-ingress:1.7.2
[root@node-2 ~]# docker pull nginx/nginx-ingress:1.7.2
 
# 下载资源清单
https://github.com/kubeguide/K8sDefinitiveGuide-V5-Sourcecode/blob/main/Chapter04/4.6.1%20nginx-ingress-controller.yaml
 
# 修改名称
[root@master-1 tmp]# mv 4.6.1\ nginx-ingress-controller.yaml nginx-ingress.yaml
 
# 编写配置文件
## 将Deployment改成DaemonSet
kind: DaemonSet
 
## 删除副本数量
  replicas: 1 
 
## 删除ingress创建资源
# mywebsite-ingress.yaml
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: mywebsite-ingress
spec:
  rules:
  - host: mywebsite.com
    http:
      paths:
      - path: /demo
        pathType: ImplementationSpecific
        backend:
          service:
            name: webapp
            port:
              number: 8080
 
# test accessing service through ingress
# curl --resolve mywebsite.com:80:192.168.18.3 http://mywebsite.com/demo/
 
# test accessing service through ingress
 
## 删除节点标签选择器
      nodeSelector:
        role: ingress-nginx-controller
 
# 启动ingress
[root@master-1 tmp]# kubectl apply -f nginx-ingress.yaml 
namespace/nginx-ingress created
serviceaccount/nginx-ingress created
clusterrole.rbac.authorization.k8s.io/nginx-ingress created
clusterrolebinding.rbac.authorization.k8s.io/nginx-ingress created
secret/default-server-secret created
configmap/nginx-config created
daemonset.apps/nginx-ingress created
 
# 查看ingress
[root@master-1 tmp]# kubectl get pod -n nginx-ingress -o wide
NAME                  READY   STATUS    RESTARTS   AGE   IP          NODE     NOMINATED NODE   READINESS GATES
nginx-ingress-28qrx   1/1     Running   0          49s   10.2.1.53   node-1   <none>           <none>
nginx-ingress-xxr4w   1/1     Running   0          49s   10.2.2.77   node-2   <none>           <none>
 
# 查看ingress资源
[root@master-1 tmp]# kubectl get ingress
 
## 注意:ingress必须创建在clusterip之上
[root@master-1 tmp]# vim nginx-svc.yaml
kind: Service
apiVersion: v1
metadata:
  name: nginx-svc
spec:
  selector:
    app: nginx-labels
  type: ClusterIP
  ports:
  - name: nginx-port
    port: 80
    targetPort: 80
    protocol: TCP
 
# 编写ingress资源
[root@master-1 tmp]# vim nginx-in.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: welcome-to-nginx
spec:
  rules:
  - host: www.ljy.com
    http:
      paths:
      - path: /
        pathType: ImplementationSpecific
        backend:
          service:
            name: nginx-svc
            port:
              number: 80
 
# 启动
[root@master-1 tmp]# kubectl apply -f nginx-in.yaml 
 
# 本地域名解析
10.0.0.111 www.ljy.com

image-20230925120838285

规则解释:

spec:
  rules:                                  # 转发规则
  - host: www.ljy.com                     # 匹配的域名
    http:                                 # 基于http协议解析
      paths:                              # 基于路径进行匹配
      - path: /                           # 匹配/路径
        pathType: ImplementationSpecific  # 路径类型
        backend:                          # 匹配后跳转的后端服务
          service:                        # 设置后端跳转到Service的配置
            name: nginx-svc               # 跳转到名为my-nginx的ClusterIP
            port:                         # 跳转到的端口
              number: 80                  # Service端口号
 
pathType路径类型支持的类型:
ImplementationSpecific 系统默认,由IngressClass控制器提供
Exact 精确匹配URL路径,区分大小写
Prefix 匹配URL路径的前缀,区分大小写

连接不同名称空间的容器方法

# ping
ping service-name.namespace-name.svc.cluster.local

服务连接服务要做到高可用的方法,就要使用service的连接方法,但是##不同命名空间的service是不通的##

## 测试
条件
service两个,一个是默认命名空间,一个是zls,这个命名空间内
连接进去默认的命名空间那个pod,去ping另一个service name,需要加特殊命令才通。

/ # ping svc-nginx03
ping: bad address 'svc-nginx03'
/ # ping svc-nginx03.zls.svc.cluster.local
PING svc-nginx03.zls.svc.cluster.local (10.1.185.55): 56 data bytes
64 bytes from 10.1.185.55: seq=0 ttl=64 time=0.057 ms

/ # ping svc-nginx02
PING svc-nginx02 (10.1.252.153): 56 data bytes
64 bytes from 10.1.252.153: seq=0 ttl=64 time=0.031 ms

## pod里也可以使用

wordpress 访问示例

[root@master-1 ai]# cat wordpress.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql01
  template:
    metadata:
      labels:
        app: mysql01
    spec:
      containers:
        - name: mysql
          image: mysql:5.7
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 3306
              name: mysql
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "123"
            - name: MYSQL_DATABASE
              value: wordpress
            - name: MYSQL_USER
              value: wp-
            - name: MYSQL_PASSWORD
              value: "123"
          volumeMounts:
            - name: mysql-persistent-storage
              mountPath: /var/lib/mysql
      volumes:
        - name: mysql-persistent-storage
          hostPath:
            path: /data/db
---
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  selector:
    app: mysql01
  ports:
    - protocol: TCP
      port: 3306

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      containers:
        - name: wordpress
          image: wordpress:latest
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
              name: http
          env:
            - name: WORDPRESS_DB_HOST
              value: mysql
            - name: WORDPRESS_DB_USER
              value: wp-
            - name: WORDPRESS_DB_PASSWORD
              value: "123"
            - name: WORDPRESS_DB_NAME
              value: wordpress
          volumeMounts:
            - name: wordpress-persistent-storage
              mountPath: /var/www/html
          resources:
            requests:
              cpu: 200m
      volumes:
        - name: wordpress-persistent-storage
          hostPath:
            path: /data/wordpress
---
apiVersion: v1
kind: Service
metadata:
  name: wordpress
spec:
  type: ClusterIP
  selector:
    app: wordpress
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: http
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: welcom-in
spec:
  rules:
  - host: www.zls.com
    http:
      paths:
      - path: /
        pathType: ImplementationSpecific
        backend:
          service:
            name: wordpress
            port:
              number: 80
 
# 启动
[root@master-1 tmp]# kubectl apply -f wordpress.yml 
 
# 查看ingress资源
[root@master-1 tmp]# kubectl get ingress
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
NAME                CLASS    HOSTS          ADDRESS   PORTS   AGE
welcome-to-nginx    <none>   www.zls.com              80      5h12m
 
# 本地域名解析(二选一,不要都填进去)
10.0.0.111 www.zls.com
#10.0.0.112 www.zls.com

image-20230925172126230