3.k8s-暴露pod和service

Kubernetes Harbor部署、Service与服务发现详解

Harbor的部署注意事项

使用的是老师的docker安装包进行部署

  1. 重新开机后要执行:

    bash 复制代码
    docker-compose up -d
  2. 所有k8s节点都要进行harbor的证书配置

导入镜像到harbor流程

bash 复制代码
# 1. 加载镜像到本地docker
docker load -i oldboyedu-mysql-v8.0.36-oracle.tar.gz

# 2. 为镜像打标签,格式为:harbor地址/项目名/镜像名:标签
docker tag mysql:8.0.36-oracle harbor250.oldboyedu.com/oldboyedu-db/mysql:8.0.36-oracle

# 3. 推送到harbor仓库
docker push harbor250.oldboyedu.com/oldboyedu-db/mysql:8.0.36-oracle

故障排查技巧三种方式

  1. 查看log日志:

    bash 复制代码
    kubectl logs <pod_name>
  2. 查看pod详细描述信息:

    bash 复制代码
    kubectl describe pod <pod_name>
  3. 进入容器内部排查:

    bash 复制代码
    kubectl exec <pod_name> -- <command> <args>

资源清单------MySQL

yaml 复制代码
[root@master231 pods]# cat 06-pods-mysql.yaml
apiVersion: v1
kind: Pod
metadata:
  name: oldboyedu-mysql
  labels:
    app: xiuxian
    version: v1
spec:
  # 重启策略默认是always
  restartPolicy: Always
  containers:
  - name: c1
    image: harbor250.oldboyedu.com/oldboyedu-db/mysql:8.0.36-oracle
    # 向容器传递参数:指定引擎
    args:
    - --character-set-server=utf8
    - --collation-server=utf8_bin
    - --default-authentication-plugin=mysql_native_password
    # 向容器传递环境变量,必须做,指定创建的数据库,用户名,密码
    env:
      # 变量的名称
    # 可以允许空密码登入
    - name: MYSQL_ALLOW_EMPTY_PASSWORD
      # 指定变量的值:意思创建了数据库叫wordpress,并创建了用户名密码
      value: "yes"
    - name: MYSQL_DATABASE
      value: "wordpress"
    - name: MYSQL_USER
      value: linux99
    - name: MYSQL_PASSWORD
      value: oldboyedu

测试验证:

bash 复制代码
kubectl exec -it oldboyedu-mysql -- mysql wordpress

暴露到k8s集群外部的方法

  • hostNetwork
  • hostPort
  • port-forward
  • nodeport

暴露K8S的Pod到集群外部之hostNetwork

yaml 复制代码
[root@master231 pods]# cat 07-pods-hostNetwork.yaml
apiVersion: v1
kind: Pod
metadata:
  name: xiuxian
spec:
  # 使用宿主机网络
  hostNetwork: true
  containers:
  - name: c1
    image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1

此时发现IP变成了物理网络,访问:

复制代码
http://10.0.0.233/

暴露K8S的Pod到集群外部之hostPort

yaml 复制代码
[root@master231 pods]# cat 08-pods-hostPort.yaml
apiVersion: v1
kind: Pod
metadata:
  name: xiuxian-001
spec:
  # 指定节点调度,节点的名称必须在etcd数据库中有记录,可以使用"kubectl get no"进行查看。
  nodeName: worker232   # 也可以不指定,会随机给节点进行调度
  containers:
  - name: c1
    image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v2
    # 对外暴露服务,有点类似于: docker run -p 90:80 ...
    ports:
      # 容器对外暴露的端口
    - containerPort: 80
      # 将宿主机的某个端口转发到容器的端口,访问直接物理机ip+90
      hostPort: 90

测试验证:由于调度到worker232节点,因此可以直接使用该节点的IP地址和端口进行访问。

复制代码
http://10.0.0.232:90/

暴露K8S的Pod到集群外部之port-forward

正常pod资源清单:

yaml 复制代码
[root@master231 pods]# cat 01-pods-single-xiuxian.yaml
apiVersion: v1
kind: Pod
metadata:
  name: xixi
spec:
  containers:
  - name: c1
    image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v2

新开一个终端添加转发规则:

bash 复制代码
# --address 0.0.0.0:监听所有网络接口。只能当前节点可以访问
# xixi:Pod 名称(或 service/xxx 服务名称)。
# 99:80:将本地的 99 端口转发到 Pod 的 80 端口
[root@master231 pods]# kubectl port-forward --address 0.0.0.0 xixi 99:80

访问测试:

复制代码
http://10.0.0.231:99/

案例------WordPress对外暴露

需求:

  • 部署MySQL到worker232节点;
  • 部署wordpress业务到worker233节点并让K8S集群能够正常访问;

资源清单如下:

yaml 复制代码
[root@master231 pods]# cat 09-pods-wordpress.yaml
apiVersion: v1
kind: Pod
metadata:
  name: db
spec:
  # 使用宿主机232部署,并且使用该网络
  nodeName: worker232
  hostNetwork: true
  containers:
  - name: db
    image: harbor250.oldboyedu.com/oldboyedu-db/mysql:8.0.36-oracle
    args:
    - --character-set-server=utf8
    - --collation-server=utf8_bin
    - --default-authentication-plugin=mysql_native_password
    env:
    - name: MYSQL_ALLOW_EMPTY_PASSWORD
      value: "yes"
    - name: MYSQL_DATABASE
      value: "wordpress"
    - name: MYSQL_USER
      value: linux99
    - name: MYSQL_PASSWORD
      value: oldboyedu

---

apiVersion: v1
kind: Pod
metadata:
  name: wp
spec:
  # 指定宿主机233部署wordpress,但此时没有指定访问方式
  nodeName: worker233
  containers:
  - name: wp
    image: harbor250.oldboyedu.com/oldboyedu-wp/wordpress:6.7.1-php8.1-apache
    env:
    - name: WORDPRESS_DB_HOST
      value: "10.0.0.232"
    - name: WORDPRESS_DB_NAME
      value: "wordpress"
    - name: WORDPRESS_DB_USER
      value: linux99
    - name: WORDPRESS_DB_PASSWORD
      value: oldboyedu
# 传递变量,数据库宿主机的IP地址,数据库的库,用户名密码

暴露WordPress业务:

bash 复制代码
[root@master231 pods]# kubectl port-forward --address 0.0.0.0 wp 80:80
# 只在当前k8s节点都可以通过80端口进行访问

访问测试:

复制代码
http://10.0.0.231/wp-admin/install.php
用户密码: admin 1

案例------ES部署到k8s(使用hostPort)

资源清单:

yaml 复制代码
[root@master231 pods]# cat 10-pods-es.yaml
apiVersion: v1
kind: Pod
metadata:
  name: oldboyedu-es
spec:
  containers:
  - name: es
    image: harbor250.oldboyedu.com/oldboyedu-elasticstack/elasticsearch:7.17.25
    ports:
      # 宿主机9200,容器9200。访问的时候直接访问该物理机的ip+9200
    - containerPort: 9200
      name: http
      hostPort: 9200

    - containerPort: 9300
      name: tcp
    env:
    - name: discovery.type
      value: "single-node"
# 单点部署

Service类型及验证服务发现和负载均衡案例

Service简介

  • Service是K8S集群的一个资源,底层基于标签来关联Pod。访问Service时可以关联到相应的Pod。
  • Service为Pod提供统一的访问入口,当Pod的IP发生变化时,会自动关联到变化后的IP。
  • 简而言之,Service为Pod提供了负载均衡和服务发现。

为什么需要service?

场景:现在起了三个rc副本,然后把它删除会发现:

  • 删除Pod后会自动拉起,但是Pod的IP地址会发生变化!
  • 这样会导致不小心删除和重启都会IP变化,所以要使用service服务通过标签进行IP的关联。

Service类型

yaml 复制代码
# 指定Service的类型,有效值为: ExternalName, ClusterIP, NodePort, and LoadBalancer。
#    ClusterIP:
#       该Service资源只能被K8S集群内部进行访问。一般用于K8S集群Pod互相访问。
#    NodePort:
#       在ClusterIP基础之上,在K8S所有的worker节点添加了端口映射规则。
#       换句话说,就是你访问K8S集群任意一个worker的某个特定端口,则会将其请求转发到集群内部的ClusterIP。
#    LoadBalancer:
#        一般情况下用在云厂商环境,如果线下想要使用该类型,则可以部署相应的组件来实现此功能。
#        该类型原生不支持,需要部署第三方组件。
#    ExternalName:
#       将K8S集群外部的某个服务映射到K8S集群内部的Service,底层采用CNAME技术实现。
#       如果不指定Service类型,不定义该字段则默认是ClusterIP。

资源清单:使用service连接rc的pod

使得无论rc的IP怎么变化,都能通过service的IP进行访问。

yaml 复制代码
[root@master231 services]# cat 01-svc-clusterIP.yaml
apiVersion: v1
kind: Service
metadata:
  name: svc-xiuxian
spec:
  # 指定Service的类型,有效值为: ExternalName, ClusterIP, NodePort, and LoadBalancer。
  #    ClusterIP:
  #       该Service资源只能被K8S集群内部进行访问。一般用于K8S集群Pod互相访问。
  #    NodePort:
  #       在ClusterIP基础之上,在K8S所有的worker节点添加了端口映射规则。
  #       换句话说,就是你访问K8S集群任意一个worker的某个特定端口,则会将其请求转发到集群内部的ClusterIP。
  #    LoadBalancer:
  #        一般情况下用在云厂商环境,如果线下想要使用该类型,则可以部署相应的组件来实现此功能。
  #        该类型原生不支持,需要部署第三方组件。
  #    ExternalName:
  #       将K8S集群外部的某个服务映射到K8S集群内部的Service,底层采用CNAME技术实现。
  #       如果不指定Service类型,不定义该字段则默认是ClusterIP。
  type: ClusterIP
  # 标签选择器,用来关联Pod
  selector:
    app: xiuxian
  # 配置端口映射
  ports:
    # 指定是Service端口号
  - port: 90
    # 指定后端容器的端口
    targetPort: 80

访问测试: service的IP+端口

bash 复制代码
curl 10.200.199.151:90

案例------kibana连接ES集群并连接filebeat

此时ES使用ClusterIP,然而kibana和filebeat使用的是NodePort

编写资源清单:一个service对应一个pod

yaml 复制代码
[root@master231 pods]# cat 11-pods-efk.yaml
apiVersion: v1
kind: Pod
metadata:
  name: oldboyedu-es
  labels:
    app: es7
spec:
  containers:
  - name: es
    image: harbor250.oldboyedu.com/oldboyedu-elasticstack/elasticsearch:7.17.25
    ports:
    - containerPort: 9200
      name: http
    - containerPort: 9300
      name: tcp
    env:
    - name: discovery.type
      value: "single-node"
---
apiVersion: v1
kind: Service
metadata:
  name: svc-es7
spec:
  type: ClusterIP
  # 指定Service的IP地址,注意自定义时要和你集群的svc网段一致(10.200.0.0/16)
  clusterIP: 10.200.0.92
  selector:
    app: es7
  ports:
  - port: 9200
    targetPort: http
---
apiVersion: v1
kind: Pod
metadata:
  name: oldboyedu-kibana
  labels:
    app: kibana
spec:
  containers:
  - name: kibana
    image: harbor250.oldboyedu.com/oldboyedu-elasticstack/kibana:7.17.25
    ports:
    - containerPort: 5601
      name: webui
    env:
    - name: ELASTICSEARCH_HOSTS
      value: "http://10.200.0.92:9200"
    - name: I18N_LOCALE
      value: "zh-CN"
---
apiVersion: v1
kind: Service
metadata:
  name: svc-kibana
spec:
  # 向外暴露端口
  type: NodePort
  selector:
    app: kibana
  ports:
  - port: 5601
    targetPort: webui
    nodePort: 30090
---
apiVersion: v1
kind: Pod
metadata:
  name: oldboyedu-filebeat
  labels:
    app: filebeat
spec:
  containers:
  - name: filebeat
    image: harbor250.oldboyedu.com/oldboyedu-elasticstack/filebeat:7.17.25
    ports:
    - containerPort: 8888
      name: tcp
---
apiVersion: v1
kind: Service
metadata:
  name: svc-filebeat
spec:
  type: NodePort
  selector:
    app: filebeat
  ports:
  - port: 8888
    targetPort: tcp
    nodePort: 30088

进行测试

bash 复制代码
# 进入filebeat容器
[root@master231 pods]# kubectl exec -it oldboyedu-filebeat -- bash

# 创建配置文件
filebeat@oldboyedu-filebeat:~$ cat > /tmp/tcp-to-es.yaml <<EOF
filebeat.inputs:
- type: tcp
  host: "0.0.0.0:8888"
output.elasticsearch:
  hosts: ["http://10.200.0.92:9200"]
  index: oldboyedu-linux99-tcp
setup.ilm.enabled: false
setup.template.name: "oldboyedu-linux99"
setup.template.pattern: "oldboyedu-linux99*"
setup.template.overwrite: false
setup.template.settings:
  index.number_of_shards: 3
  index.number_of_replicas: 0
EOF

# 启动filebeat
filebeat@oldboyedu-filebeat:~$ filebeat -e -c /tmp/tcp-to-es.yaml --path.data=/tmp/xixi

发送测试数据:

bash 复制代码
[root@master231 services]# echo www.oldboyedu.com | nc 10.0.0.233 30088

注意:

  • 命令 nc 10.0.0.233 30088 的作用是:通过节点物理IP和NodePort,将测试数据发送到Filebeat的TCP输入端口(8888),最终由Filebeat转发到Elasticsearch。
  • host: "0.0.0.0:8888" 是为了让Filebeat在容器内监听所有网络接口,确保外部(通过NodePort 30088或Service)的TCP数据能被正确接收并转发到Elasticsearch。

查看kibana的webUI:

复制代码
http://10.0.0.232:30090/app/management/data/index_management/indices

关键字段解析

yaml 复制代码
ports:
  - port: 5601        # Service 的端口,内部互相访问的端口
    targetPort: webui # 转发到 Pod 的端口,容器内的实际端口
    nodePort: 30090   # 节点暴露的端口,外部访问(仅 NodePort 类型需要)
  • 集群内部 :通过 svc-filebeat:5601 访问。
  • 集群外部 :通过 http://<任意节点IP>:30090 访问。

NodePort和HostPort对比

  • NodePort:所有k8s节点都可以访问。
  • HostPort:只能被调度的节点访问。
  • 所以NodePort有高可用性

服务发现的体现

服务发现(Service Discovery)
作用:为Kubernetes Service提供端口映射依据。Service通过targetPort匹配Pod的containerPort,将流量转发到容器。

示例:

yaml 复制代码
# Pod 定义
containers:
  - ports:
      - containerPort: 8080
        name: app-port

# Service 定义
spec:
  ports:
    - port: 80              # Service 对外端口
      targetPort: app-port  # 转发到 Pod 的 8080 端口(通过名称匹配)

命令行操作

bash 复制代码
# 查看所有service
kubectl get svc -o wide

# 查看service详细信息
kubectl describe svc svc-filebeat

# 进入容器
kubectl exec -it oldboyedu-filebeat -- bash

拓展:服务为什么要使用Service

1. Pod的动态性导致IP不稳定

  • Pod是临时资源,生命周期可能因重启、扩缩容、节点故障等原因变化,其Cluster IP会动态改变。
  • 直接访问Pod IP的问题:一旦Pod重建,IP变化,依赖方(如其他Pod)会访问失败。
  • Service的价值:提供固定的访问入口(Service名称/Cluster IP),自动关联后端Pod(通过标签选择器),屏蔽Pod IP变化的影响。

2. 实现负载均衡和流量分发

  • 多个Pod副本(如Deployment管理的Pod)提供同一服务时,Service会自动将流量负载均衡到所有健康Pod。
  • 例如:3个Nginx Pod副本,Service通过轮询或会话亲和性分发请求,避免单Pod负载过高。

3. 简化集群内服务发现

  • K8s集成DNS服务 (CoreDNS),其他Pod可通过Service名称访问服务(如http://svc-nginx:80),无需硬编码IP/端口。

4. 支持外部访问(NodePort/Ingress依赖)

  • 外部访问集群内服务时,需通过Service作为桥梁(如NodePort暴露节点端口、Ingress绑定Service)。
相关推荐
Alice_whj3 小时前
AI云原生笔记
人工智能·笔记·云原生
❀͜͡傀儡师3 小时前
使用 Docker 部署 Puter 云桌面系统
运维·docker·容器
人间打气筒(Ada)3 小时前
Kubernetes核心技术-service详解
云原生·容器·kubernetes·云计算·devops·service·service代理
匀泪4 小时前
云原生(nginx环境设定)
java·nginx·云原生
切糕师学AI4 小时前
Kubernetes Deployment 详解
容器·kubernetes
swbook4 小时前
k8s1.35.1二进制部署
docker·kubernetes·k8s·kubectl-ai
运维螺丝钉5 小时前
Kubernetes之Istio应用
容器·kubernetes·istio
2501_924878735 小时前
中小电商自建直播间成本降47%:AI口播智能体轻量部署(含Docker+OBS链路)
人工智能·docker·容器·排序算法·宽度优先
uNhPiLgvQDpJ5 小时前
基于STM32的实验室环境检测系统:温湿度、烟雾、空气质量检测和报警功能
kubernetes