---
# System prepended metadata

title: '[k8s] Service'
tags: [kubernetes]

---

[k8s] Service
========
###### tags: `kubernetes`
:::info
+ 連接到 Pod 有兩種方式，一種是建立 `Service` 另一種是用 `port-forward`
+ `Service` 的目的就是提供單一的 endpoint 給 clients 去訪問其背後所代理的 `Pods`
:::
# port-forward
+ 就是把 host 上的某個 port 連線至 Pod 的對外 port
+ `kubectl port-forward pod/${podname} ${NodePort}:${PodPort}`

# How to using "Service" to expose your application
+ **ClusterIP**: `預設值`，代表這個 Service 只能在相同的 Cluster 內使用，無法讓外部使用。
+ **NodePort**: 
    + 讓外部可以連到內部使用
    + an open port on every node of your cluster. Kubernetes transparently routes incoming traffic on the NodePort to your service, even if your application is running on a different node.
    + assigned from a pool of cluster-configured NodePort ranges (typically 30000–32767)
+ **LoadBalancer**: Using a LoadBalancer service type automatically deploys an external load balancer. This external load balancer is associated with a specific IP address and routes external traffic to a Kubernetes service in your cluster.
    + 這個屬性是強化版的 NodePort 
    + 可惜 LoadBalancer 目前只有雲端服務，如：GCP、AWS等等有支援而已，minikube 目前暫不支援
+ **ExternalName**: 讓不同 namespace 中的以 ClusterIP 形式生成的 Service 可以利用 ExternalName 設定的外部名稱，藉以連到指定的 namespace 中的 Service

![](https://i.imgur.com/7BPA0ki.png =500x)


## NodePort
![](https://i.imgur.com/kdZaaqb.png =300x)

```yaml=
apiVersion: v1
kind: Service
metadata:
  name: helloworld
  labels:
    app: frontend
    environment: develop
spec:
  type: NodePort
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
      nodePort: 32700
  selector:
    app: frontend
```
+ ***nodePort***: 指的是機器上的 Port 要對應到該 Service 上
    + range: 30000 ~ 32767
+ ***port***: 建立好的 Service 要以哪個 port 連接到 Pod 上
+ ***targetPort***: targetPort: 指的是目標 Pod 的 port
    + 如果不指定，則same as port
+ ***selectors***: 連接到正確的pod

### 或可利用 port-forwad
```shell=
kubectl create deployment hello-minikube --image=docker.io/nginx:1.23
kubectl expose deployment hello-minikube --type=NodePort --port=80
kubectl port-forward service/hello-minikube 7080:80
```
## TargetPort
```yaml=
apiVersion: v1
kind: Pod
metadata:
  app: my-api
spec:
  containers:
  - name: my-api
    image: my-api
    ports:
    - containerPort: 8080
      name: my-api
```
```yaml=
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-api
  ports:
  - port: 443
    targetPort: my-api
```

## ClusterIP
![](https://i.imgur.com/qaXu9US.png)

![](https://i.imgur.com/AchFIGt.png)

#### note
1. 因為application pod 和 redis service 在相同的 namespace, 所以可以直接使用service name "redis"來做存取.
2. 若要連線到`dev` namespace的redis，為`redis.dev.svc.cluster.local`
    ![](https://i.imgur.com/KrR6XQR.png =300x)


## definition file
```yaml=
apiVersion: v1
kind: Service
metadata: 
  name: back-end
spec: 
  type: ClusterIP
  ports:
    - targetPort: 80
      port: 80
  selector:
    app: myapp
    type: back-end
```

## imperative commands
```shell=
k expose pod redis --port=6379 --name=redis-service
```

## LoadBalancer
![](https://i.imgur.com/7TroR5q.jpg)

![](https://i.imgur.com/izulhKZ.jpg)




```yaml=
apiVersion: v1
kind: Service
metadata:
  name: ar-remote-assist
  namespace: ingress-ar
  annotations:
    service.beta.kubernetes.io/azure-load-balancer-resource-group: ar-remote-assist
spec:
  loadBalancerIP: 137.135.8.185
  type: LoadBalancer
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: 8080
    - name: https
      port: 443
      protocol: TCP
      targetPort: 8443
  selector:
    app: ar-remote-assist

```
externalTrafficPolicy: ***Local*** || ***Cluster***

## reference
+ [Kubernetes 那些事 — Service 篇](https://medium.com/andy-blog/kubernetes-%E9%82%A3%E4%BA%9B%E4%BA%8B-service-%E7%AF%87-d19d4c6e945f)