kubernetes-service资源

service资源

NodeIP
节点对外提供访问的IP

clusterIP
用来动态发现和负均衡POD的IP

PodIP
提供PoD使用的IP

## Service提供四种资源:
ExternalName
ClusterIP
NodePort
LoadBalancer

image-20230925153524780

资源清单创建名称空间

## 多写一个apiVersion 它的kind指定Namespace  name指定这个名称空间的名字
apiVersion: v1
kind: Namespace
metadata:
  name: hg

## 查看指定名称空间所有资源
kubectl get all -n Namespace

编写service资源清单(cluster-ip)

[root@master-1 web]# vim nginx.yml 
apiVersion: v1
kind: Namespace
metadata:
  name: hg

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-dp
  namespace: hg
  labels:
    nginx: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:alpine
        name: nginx
        imagePullPolicy: IfNotPresent

---

apiVersion: "v1"         ## Service的apiVersion也是v1
kind: "Service"          ## kind 指定为 Service
metadata:
  name: nginx-svc        ## 定义Service的名字
  namespace: hg          ## 指定名称空间
spec:
  selector:
    app: nginx           ## 指定pod的标签 通过pod标签去发现后端的pod
  ports:
  - name: nginx-port     ## 定义这个服务的名字
    port: 80             ## 下面的type是ClusterIP 所以这里是ClusterIP的端口
    protocol: TCP        ## 指定协议
    targetPort: 80       ## 指定pod的端口 映射到上面的port
  type: ClusterIP        ## type指定Service的类型是ClusterIP

## 启动
[root@master-1 web]# kubectl apply -f nginx.yml

## 查看service
[root@master-1 web]# kubectl get service -n hg
NAME        TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
nginx-svc   ClusterIP   10.1.187.94   <none>        80/TCP    5m47s

[root@master-1 web]# kubectl get svc -n hg
NAME        TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
nginx-svc   ClusterIP   10.1.187.94   <none>        80/TCP    6m4s

## 查看pod
[root@master-1 web]# kubectl get pod -n hg -o wide
NAME                       READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
nginx-dp-c579f8485-gxdwv   1/1     Running   0          7m    10.2.1.105   node-1   <none>           <none>

## 查看pod和Service是否在一个名称空间
[root@master-1 web]# kubectl get all -n hg
NAME                           READY   STATUS    RESTARTS   AGE
pod/nginx-dp-c579f8485-gxdwv   1/1     Running   0          7m57s

NAME                TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
service/nginx-svc   ClusterIP   10.1.187.94   <none>        80/TCP    7m57s

NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-dp   1/1     1            1           7m57s

NAME                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-dp-c579f8485   1         1         1       7m57s

## 查看service详细信息 会发现 Endpoints 里通过selector指定pod标签自动发现同一名称空间的pod
[root@master-1 web]# kubectl describe svc -n hg
Name:              nginx-svc
Namespace:         hg
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx
Type:              ClusterIP
IP:                10.1.187.94
Port:              nginx-port  80/TCP
TargetPort:        80/TCP
Endpoints:         10.2.1.105:80
Session Affinity:  None
Events:            <none>

## 查看clusterip的nginx内容
[root@master-1 web]# curl 10.1.187.94
<!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示例
[root@master-1 web]# vim mysql.yml 
apiVersion: v1
kind: Namespace
metadata:
  name: hg

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql57
  namespace: hg
spec:
  replicas: 1
  selector:
    matchLabels:
      name: mysql57
  template:
    metadata:
      labels:
        name: mysql57
    spec:
      containers:
      - name: mysql57
        image: mysql:5.7
        imagePullPolicy: IfNotPresent
        env:
          - name: MYSQL_ROOT_PASSWORD
            value: "123"
          - name: MYSQL_DATABASE
            value: "wp"
          - name: MYSQL_USER
            value: "wpuser"
          - name: MYSQL_PASSWORD
            value: "123"

---

apiVersion: v1
kind: Service
metadata:
  name: mysql
  namespace: hg
spec:
  selector: 
    name: mysql57
  ports:
  - name: mysql-port
    port: 3306
    protocol: TCP
    targetPort: 3306
  type: ClusterIP

## 启动
[root@master-1 web]# kubectl apply -f mysql.yml

## 查看mysql-svc详细信息
[root@master-1 web]# kubectl describe svc -n hg
Name:              mysql
Namespace:         hg
Labels:            <none>
Annotations:       <none>
Selector:          name=mysql57
Type:              ClusterIP
IP:                10.1.215.229
Port:              mysql-port  3306/TCP
TargetPort:        3306/TCP
Endpoints:         10.2.1.108:3306
Session Affinity:  None
Events:            <none>

## 连接mysql
[root@master-1 web]# mysql -uroot -p123 -h 10.1.215.229
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
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(10.1.0.10)

/ # cat /etc/resolv.conf 
nameserver 10.1.0.10
search hg.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

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

[root@master-1 web]# 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   4d21h

[root@master-1 web]# 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.10:53,10.2.0.11:53
Port:              dns-tcp  53/TCP
TargetPort:        53/TCP
Endpoints:         10.2.0.10:53,10.2.0.11:53
Port:              metrics  9153/TCP
TargetPort:        9153/TCP
Endpoints:         10.2.0.10:9153,10.2.0.11:9153
Session Affinity:  None
Events:            <none>

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

[root@master-1 web]# kubectl describe svc -n hg nginx-svc 
Name:              nginx-svc
Namespace:         hg
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx
Type:              ClusterIP
IP:                10.1.187.94
Port:              nginx-port  80/TCP
TargetPort:        80/TCP
Endpoints:         10.2.1.105:80
Session Affinity:  None
Events:            <none>

任何POD只要ping svc的名称就可以进行通信
ping service-name.namespace-name.svc.cluster.local

image-20230925163722362

NodePort

存在问题:

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

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

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

[root@master-1 web]# vim nginx.yml 
apiVersion: v1
kind: Namespace
metadata:
  name: hg

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-dp
  namespace: hg
  labels:
    nginx: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:alpine
        name: nginx
        imagePullPolicy: IfNotPresent

---

apiVersion: "v1"
kind: "Service"
metadata:
  name: nginx-svc
  namespace: hg
spec:
  selector:
    app: nginx
  ports:
  - name: nginx-port
    port: 80            ## clusterIP的端口号
    protocol: TCP       ## 协议类型
    targetPort: 80      ## POD的端口
    nodePort: 30001     ## NodeIP的端口号,也就是对外用户访问的端口号(范围为30000-32767)
  type: NodePort        ## 指定type类型为NodePort

[root@master-1 web]# kubectl apply -f nginx.yml 

[root@master-1 web]# kubectl get svc -n hg
NAME        TYPE       CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
nginx-svc   NodePort   10.1.73.7    <none>        80:30001/TCP   47s

image-20230925164553438

解决方法:

只写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-20230925172122035

部署nginx-lngress

# 拉取镜像
[root@node-1 ~]# docker pull nginx/nginx-ingress:1.7.2
[root@node-2 ~]# docker pull nginx/nginx-ingress:1.7.2

# 下载资源清单
[root@master-1 ~]# wget https://github.com/kubeguide/K8sDefinitiveGuide-V5-Sourcecode/blob/main/Chapter04/4.6.1%20nginx-ingress-controller.yaml

# 改名
[root@master-1 ~]# mv 4.6.1\ nginx-ingress-controller.yaml /root/ingress/nginx-ingress.yml

# 修改配置文件
## 删除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
## 删除节点标签选择器
      nodeSelector:
        role: ingress-nginx-controller       
## 删除副本数
replicas: 1

## 将Deployment改成DaemonSet
kind: DaemonSet

## 启动ingress
[root@master-1 ingress]# kubectl apply -f nginx-ingress.yml 
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 ingress]# kubectl get pod -n nginx-ingress 
NAME                  READY   STATUS    RESTARTS   AGE
nginx-ingress-hflhf   1/1     Running   0          5h42m
nginx-ingress-pd8rp   1/1     Running   0          5h42m

## 查看ingress资源
[root@master-1 ingress]# kubectl get ingress

## 注意:ingress必须创建在clasterip之上
[root@master-1 web]# cat nginx-ig.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-dp
  labels:
    nginx: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:alpine
        name: nginx
        imagePullPolicy: IfNotPresent

---

kind: Service
apiVersion: v1
metadata:
  name: nginx-svc
spec:
  selector:
    app: nginx
  type: ClusterIP
  ports:
  - name: nginx-port
    port: 80
    targetPort: 80
    protocol: TCP

---

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: welcome-to-nginx
spec:
  rules:
  - host: www.hg.com
    http:
      paths:
      - path: /
        pathType: ImplementationSpecific
        backend:
          service:
            name: nginx-svc
            port:
              number: 80

## 规则解释
spec:
  rules:                                  # 转发规则
  - host: www.hg.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路径的前缀,区分大小写

## 启动
[root@master-1 web]# kubectl apply -f nginx-ig.yml

## 访问www.hg.com

image-20230925181921423