k3sでTraefik Ingressを使ってアプリケーションを公開する

## k3sでTraefik Ingressを使ってアプリケーションを公開する

AWS Cloud9上にk3sをインストールして遊んでいるのですが、Ingressを使ってWebアプリケーションをクラスタ外部に公開したい、となったときにIngress Controllerの設定が必要になりました。

k3sにはデフォルトでTraefikというIngress Controllerが組み込まれているようなので、今回は簡単にそちらをセットアップして使えるようにしたいと思います。

k3sのバージョンは以下の通り。

```
# k3s --version
k3s version v1.29.5+k3s1 (4e53a323)
go version go1.21.9
```

### Traefix Ingress Controllerとは

Traefik Ingress ControllerはKubernetesで利用可能なIngress Controllerの一種。k3sをインストールするとデフォルトでTraefix Ingress Contollerを使えるようになるみたいです。

https://docs.k3s.io/networking/networking-services#traefik-ingress-controller

実機上でIngress Classを確認してみると、確かに`traefik.io/ingress-controller`という名前のIngress Controllerが存在することを確認できます。

Ingressをデプロイする際には`spec.ingressClassName`に`traefix`を指定すれば良さそうです。


```
# kubectl describe ingressclass
Name:         traefik
Labels:       app.kubernetes.io/instance=traefik-kube-system
              app.kubernetes.io/managed-by=Helm
              app.kubernetes.io/name=traefik
              helm.sh/chart=traefik-25.0.3_up25.0.0
Annotations:  ingressclass.kubernetes.io/is-default-class: true
              meta.helm.sh/release-name: traefik
              meta.helm.sh/release-namespace: kube-system
Controller:   traefik.io/ingress-controller
Events:       <none>
```

### Ingressをデプロイしてみる

以下のようなマニフェストを用意しました。
Ingressのマニフェストのspec.ingressClassNameの部分で明示的に`traefik`を指定しています。ここについてはIngress Classの定義上、`ingressclass.kubernetes.io/is-default-class: true`のアノテーションが付いているので、明示的に指定しなくても問題はなさそうです。

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-app
  namespace: sample-namespace
spec:
  selector:
    matchLabels:
      app: sample-app
  replicas: 3
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
      - image: docker.io/httpd:2.4
        name: sample-app
        ports:
        - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: sample-app-service
  namespace: sample-namespace
spec:
  selector:
    app: sample-app
  ports:
  - port: 8085
    targetPort: 80
    name: http
    protocol: TCP
  type: ClusterIP

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: sample-app-ingress
spec:
  ingressClassName: traefik
  rules:
  - host: k8s.consulting-io.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: sample-app-service
            port: 
              number: 8085
```

デプロイ後、Ingressリソースを確認すると以下のような状態。traefikを使用してIngressがデプロイされていることが確認できます。

```
$ kubectl get ingress
NAME                 CLASS     HOSTS                   ADDRESS        PORTS   AGE
sample-app-ingress   traefik   k8s.consulting-io.com   172.31.40.27   80      3d8h
```

ブラウザからもアクセスできました。

![スクリーンショット 2025-03-12 22.51.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3880214/2597b242-b61a-4d21-b4ce-e229846f9960.png)
example.com

### 参考

k3sの公式ドキュメントには以下のような記述があり、TrefifxでIngressを作成するとLoadBalancerタイプのサービスが作成されて、このサービス経由でクラスタ外部との通信が行われるようです。

>The Traefik ingress controller deploys a LoadBalancer Service that uses ports 80 and 443, advertises the LoadBalancer Service's External IPs in the Status of Ingress resources it manages.


https://docs.k3s.io/networking/networking-services#traefik-ingress-controller

実際に`kube-system`のサービスを確認するとLoadBalancerタイプのサービスがちゃんと作成されていました。

```
$ kubectl get svc -n kube-system
NAME             TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)                      AGE
kube-dns         ClusterIP      10.43.0.10      <none>         53/UDP,53/TCP,9153/TCP       276d
metrics-server   ClusterIP      10.43.189.172   <none>         443/TCP                      276d
traefik          LoadBalancer   10.43.128.184   172.31.40.27   80:30323/TCP,443:31601/TCP   276d
```

 ### まとめ

k3sではデフォルトでTraefik Ingressが利用可能になっており、特に何も工夫しなくてもIngressの作成からクラスタ上のアプリケーションの公開まで簡単にできました。

Nginx Ingressもインストールすれば利用可能みたいですが、とにかく手っ取り早くやりたいという方はTraefik Ingressがおすすめです。

### 参考記事
https://docs.k3s.io/networking/networking-services#traefik-ingress-controller

https://doc.traefik.io/traefik/providers/kubernetes-ingress/