---
# System prepended metadata

title: 部署 Nginx 服務，並透過 istio ingressgateway 使用 https 訪問
tags: [工具]

---

# 部署 Nginx 服務，並透過 istio ingressgateway 使用 https 訪問


## 環境準備

* 已安裝好 istio

```
$ kubectl -n istio-system get pod
NAME                                    READY   STATUS    RESTARTS   AGE
istio-cni-node-5kmfh                    1/1     Running   0          18h
istio-cni-node-975fn                    1/1     Running   0          18h
istio-cni-node-9jqsq                    1/1     Running   0          18h
istio-cni-node-9n8s6                    1/1     Running   0          18h
istio-cni-node-d5d4z                    1/1     Running   0          18h
istio-ingressgateway-5b6548c6d6-n6x64   1/1     Running   0          18h
istiod-d498fb64c-d9w5x                  1/1     Running   0          18h
jaeger-76444674f-s2nqj                  1/1     Running   0          18h
kiali-6d774d8bb8-6n6zj                  1/1     Running   0          18h
ztunnel-dc56s                           1/1     Running   0          18h
ztunnel-f4t5s                           1/1     Running   0          18h
ztunnel-mfxxn                           1/1     Running   0          18h
ztunnel-vrbs2                           1/1     Running   0          18h
ztunnel-w4xkp                           1/1     Running   0          18h
```

## 部署 Nginx
* 在 demo namespace 設定 `istio.io/dataplane-mode=ambient` label
```
$ kubectl create ns demo

$ kubectl label namespace demo istio.io/dataplane-mode=ambient
```
* 建立 Nginx deployment
```
$ kubectl -n demo create deploy web --image=nginx --port=80

$ kubectl -n demo expose deploy web --name=svc-web --target-port=80 --port=80
```

* 建立自簽憑證
```
$ git clone https://github.com/cooloo9871/SelfSigned-RootCA.git;cd SelfSigned-RootCA/

# ip 為 istio ingressgateway svc ip
$ ./mk create nginx.k8s.com 192.168.1.35

# 需要有 dns server 做名稱解析
$ host nginx.k8s.com
nginx.k8s.com has address 192.168.1.35
```

* 建立 secret，需要在 `istio-system` namespace 上產生，提供給 ingressgateway 使用

```
$ kubectl -n istio-system create secret tls tls-nginx --cert=cert.pem --key=cert-key.pem
```

## 設定 istio

```
$ nano istio.yaml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: nginx-gateway
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 443
        name: https
        protocol: HTTPS
      tls:
        mode: SIMPLE
        credentialName: tls-nginx
      hosts:
        - nginx.k8s.com
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: nginx-vs
  namespace: demo
spec:
  hosts:
  - "nginx.k8s.com"
  gateways:
  - istio-system/nginx-gateway
  http:
  - route:
    - destination:
        host: svc-web.demo.svc.cluster.local
        port:
          number: 80
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: nginx
  namespace: demo
spec:
  host: svc-web.demo.svc.cluster.local
  trafficPolicy:
    tls:
      mode: DISABLE
```

```
$ kubectl apply -f istio.yaml
```
```
$ kubectl -n istio-system get gateway.networking
NAME            AGE
nginx-gateway   11s

$ kubectl -n demo get virtualservice
NAME       GATEWAYS            HOSTS               AGE
nginx-vs   ["nginx-gateway"]   ["nginx.k8s.com"]   30s

$ kubectl -n demo get destinationrule
NAME    HOST                             AGE
nginx   svc-web.demo.svc.cluster.local   43s
```


## 驗證

* 將 `ca.pem` 匯入到 client 後就可以使用 https 訪問
* 以下為 ubuntu 24.04 匯入自簽憑證設定
```
$ sudo cp ca.pem /usr/share/pki/trust/anchors/

$ sudo cp ca.pem /etc/pki/trust/anchors/

$ sudo update-ca-certificates --fresh
```
```
$ curl https://nginx.k8s.com
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
......
```

* 環境清除
```
$ kubectl delete -f istio.yaml

$ kubectl -n istio-system delete secret tls-nginx
```
## 使用 cert-manager 自簽憑證

### 0. 環境準備

1. 已安裝好 istio 以及 cert-manager

### 1.先建立 SelfSigned Issuer → 再用它簽一個 CA → 用 CA 建一個 ClusterIssuer

```
$ nano cert.yaml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: selfsigned-issuer
  namespace: cert-manager
spec:
  selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: istio-ca
  namespace: cert-manager
spec:
  isCA: true
  duration: 2160h             # 90d
  renewBefore: 720h           # 30d
  commonName: istio-ca
  secretName: istio-ca-secret
  issuerRef:
    name: selfsigned-issuer
    kind: Issuer
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: istio-ca-clusterissuer
spec:
  ca:
    secretName: istio-ca-secret
```

* 部署以及檢查資源
```
$ kubectl apply -f cert.yaml

$ kubectl -n cert-manager get Issuer
NAME                READY   AGE
selfsigned-issuer   True    32s


$ kubectl -n cert-manager get Certificate
NAME       READY   SECRET            AGE
istio-ca   True    istio-ca-secret   47s

$ kubectl get ClusterIssuer
NAME                     READY   AGE
istio-ca-clusterissuer   True    87m

$ kubectl -n cert-manager get secret istio-ca-secret
NAME              TYPE                DATA   AGE
istio-ca-secret   kubernetes.io/tls   3      98m
```


### 2. 建立 HTTPS 憑證

* 使用 `istio-ca-clusterissuer` 這個 ClusterIssuer 來簽發憑證，憑證簽發後會把 公鑰和私鑰放在 `nginx-cert-tls` secret。
* `dnsNames:` 就是 憑證的 主體名稱（SANs），也是服務對外的 domain，也需要將名稱解析到 istio ingressgateway 的 svc ip。

```
$ nano nginx-cert.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: nginx-cert
  namespace: istio-system
spec:
  duration: 2160h             # 90d
  renewBefore: 720h           # 30d
  secretName: nginx-cert-tls
  dnsNames:
    - nginx.k8s.com
  issuerRef:
    name: istio-ca-clusterissuer
    kind: ClusterIssuer

$ kubectl apply -f nginx-cert.yaml

$ kubectl -n istio-system get Certificate nginx-cert
NAME         READY   SECRET           AGE
nginx-cert   True    nginx-cert-tls   3h25m

$ kubectl -n istio-system get secret nginx-cert-tls
NAME             TYPE                DATA   AGE
nginx-cert-tls   kubernetes.io/tls   3      101m
```

### 3. 建立 Istio Gateway 與 VirtualService
* 設定 Istio 的流量路由，目標是讓外部流量透過 HTTPS 進入 Istio Ingress Gateway，然後轉發到內部 Nginx Service。
```
$ nano istio2.yaml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: nginx-gateway
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: nginx-cert-tls  # 對應憑證 Secret
    hosts:
    - nginx.k8s.com
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: nginx-vs
  namespace: demo
spec:
  hosts:
  - nginx.k8s.com
  gateways:
  - istio-system/nginx-gateway
  http:
  - route:
    - destination:
        host: svc-web.demo.svc.cluster.local
        port:
          number: 80
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: nginx
  namespace: demo
spec:
  host: svc-web.demo.svc.cluster.local
  trafficPolicy:
    tls:
      mode: DISABLE

$ kubectl apply -f istio2.yaml
```

### 3. 將 ca.pem 匯入到每一個 client 上

```
$ kubectl -n cert-manager get secret istio-ca-secret -o jsonpath='{.data.ca\.crt}' | base64 -d > ca.pem
```
* 以下為 ubuntu 24.04 匯入自簽憑證設定
```
$ sudo cp ca.pem /usr/local/share/ca-certificates/ca.crt

$ sudo update-ca-certificates
```
### 4. 測試

* 可以直接透過 https 訪問
```
$ curl https://nginx.k8s.com
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
```


![image](https://hackmd.io/_uploads/Bya288nuxx.png)




