NGINX Ingress ControllerによるIPアクセス制御

KubernetesAKS)に複数のWebアプリケーションがデプロイされていて、それぞれに対し特定のIPアドレスからのみアクセスを許可する方法を試してみました。

大まかな手順は下のとおりです。

  1. 事前準備として、HelmでIngress Controllerをデプロイする。
  2. アクセス制御として、ホワイトリストを指定したIngressリソースをデプロイする。

事前準備

Helmのインストール

公式の手順に従い、インストールします。

sudo apt-get update
curl https://helm.baltorepo.com/organization/signing.asc | sudo apt-key add -
sudo apt-get install apt-transport-https --yes
echo "deb https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt-get update
sudo apt-get install helm

Ingress Controllerのデプロイ

Ingress用のnamespaceを作っておきます。

kubectl create namespace ingress-basic

HelmでNGINX Ingress Controllerをデプロイします。AKSの公式手順ではnodeSelectorを指定していますが、Nodeの種類が複数あるわけではないので省き、レプリカも1に減らしています。

またこのとき externalTrafficPolicy=Local を指定することが重要です。これによってリクエストの送信元IPを扱うことができるようになります。指定しない場合、送信元IPによるアクセス制御はできません。

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

helm install nginx-ingress ingress-nginx/ingress-nginx \
    --namespace ingress-basic \
    --set controller.replicaCount=1 \
    --set controller.service.externalTrafficPolicy=Local

デプロイされたリソースを確認してみます。

kubectl --namespace ingress-basic get deployments

NAME                                     READY   UP-TO-DATE   AVAILABLE   AGE
nginx-ingress-ingress-nginx-controller   1/1     1            1           17h
kubectl --namespace ingress-basic get services

NAME                                               TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE
nginx-ingress-ingress-nginx-controller             LoadBalancer   10.0.190.67   xx.xx.xx.xx   80:31238/TCP,443:32076/TCP   17h
nginx-ingress-ingress-nginx-controller-admission   ClusterIP      10.0.155.88   <none>        443/TCP                      17h

検証用アプリケーションのデプロイ

2つのnamespaceを作成し、それぞれにWebサーバーのPodを立ち上げ、Serviceでクラスター内に公開しておきます。

kubectl create namespace app1
kubectl create namespace app2
kubectl -n app1 run webapp1 --image=nginx
kubectl -n app2 run webapp2 --image=httpd
kubectl -n app1 expose pod webapp1 --port=80
kubectl -n app2 expose pod webapp2 --port=80

アクセス制御の設定

Ingressリソースのデプロイ

それぞれのnamespaceに、WebサーバーServiceへのルーティングを定義したIngressを作成します。このときannotationsのwhitelist-source-rangeで、送信元IPのホワイトリストを指定できます。

注意点としてspec.rulesのbackend.service.nameでは、ServiceのFQDNを指定できません。したがってIngressを作成するnamespaceは、Serviceと同じである必要があります。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/whitelist-source-range: aa.aa.aa.aa/32
  name: ingress1
  namespace: app1
spec:
  rules:
    - http:
        paths:
          - backend:
              service:
                name: webapp1
                port: 
                  number: 80
            path: /app1
            pathType: Prefix
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/whitelist-source-range: bb.bb.bb.bb/32
  name: ingress2
  namespace: app2
spec:
  rules:
    - http:
        paths:
          - backend:
              service:
                name: webapp2
                port: 
                  number: 80
            path: /app2
            pathType: Prefix

動作確認

app1にaa.aa.aa.aaのIPアドレスからアクセスします。

f:id:kazkokk:20210614220523p:plain

app2にbb.bb.bb.bbのIPアドレスからアクセスします。

f:id:kazkokk:20210614220910p:plain

app2に許可されていないaa.aa.aa.aaのIPアドレスからアクセスします。

f:id:kazkokk:20210614220927p:plain

許可されていないIPアドレスからのアクセスは、NGINX Ingress Controllerがエラーを返していることがわかりますね!

CKA (Certified Kubernetes Administrator) 受験記

CKA受験記

2021年3月と4月にCKA (Certified Kubernetes Administrator)を受験し、合格しました。ちょうどブログを書き始めてみようと思い立ったこともあり、合格までの道のりで参考になりそうなことを書き残します。15年ぶりくらいにブログを書くので、読みづらい部分もあるかもしれませんがよろしくお願いします。

技術的な背景

私のKubernetesとの関わりとして、数年前からDocker実行環境を構築する業務に携わっていました。主にDocker Swarm Modeでクラスターを構築していましたが、Azure App Serviceに鞍替えし、ちょっとだけAWS Fargateなんかも触っていました。

一昨年くらいからAKSを扱うようになりましたが、アーキテクチャとか構築の方針を決めることが主で、実作業はほとんど部下に任せていました。腕が鈍らないように、ごくたまに自分でも作業するようにはしていました。

どう勉強したか

結論から言うと、これだけしっかりやれば十分でした。

  • UdemyのCKA対策講座

当初は、もともと試験勉強にお金をかけることは好きではないので、無料で出来ることからやってみました。具体的には、

  • Kubernetes The Hard Way
  • 上で構築した環境で色々コマンドを叩いてみる

といったことをしましたが、結果的には効果が薄かったです。特にHard Wayはkubeadmで隠蔽される部分の理解が主という印象で、CKA対策としてはほとんど時間の無駄でした。

サンプル問題とかを見つつ、このままではダメだと思い、腰を据えて勉強するべく教材を探し始めました。3つくらい候補がありましたが、Udemyが頻繁に90%超えのセールをしているのと、買い切りで済むのでこれを選びました。

UdemyのCKA対策講座は以下の特徴があります。

  • 解説ビデオと練習問題で構成される
  • かなりのボリュームがある(ビデオだけで18.5時間)
  • 練習問題は本物のKubernetes環境を使う事ができる
  • たまにエラーで練習問題がリセットされてしまうので注意(時間をかけた問題が消えると悲しいので、途中で採点したりしていました。何度でもできるので。)
  • ビデオは英語(多分インド訛り。若干とっつきづらいが、慣れれば問題ない。英語字幕はあるが、調整されていないビデオも多く、あまり役立ちませんでした。アメリカ英語しか聞いていないとつらいかもしれません。)

一周消化するのに50時間くらいはかかったと思います。結局、受験予定日までに一周しかできませんでした。

試験

実際の試験のプロフィールは各所に情報があるので任せるとして、受験してみての気づき等を書いていきます。

まず受験の結果は58点で不合格でした。再受験できることを知っていたので織り込み済みではありました。その後、Udemyで苦手な分野を復習して、練習問題も何度か実施してリヴェンジしたところ、80点で合格となりました。

心得やコツ

勉強やkubectlコマンドを打てるようになる以外で以下のことをやっておくと、合格の可能性が高まると思います。

dry-runでyamlの雛形を作ること慣れておく

一番重要です。これができないと時間までに終了することは難しいと思います。公式ドキュメントからサンプルを拾ってくることもできますが、こちらの方が時間を大幅に短縮できます。

補完機能を有効にする

タイプミスで時間を浪費しないためにも入れましょう。Kubernetes公式ドキュメントに、補完機能を有効にする方法が載っています。

kubectl Cheat Sheet

参照するドキュメントをブックマーク登録しておく

サンプルコードを利用することが多くなります。検索してもいいですが、これも時間を浪費しないために予め登録しておきましょう。CKA用のブックマークを公開してくれている人もいます。自分で作るのがベストだとは思いますが、面倒であれば先人の知恵をいただきましょう。

すぐできない問題は飛ばす

時間がかなりギリギリです。難しい問題は点数の配分も高いですが、解くまでにかかる時間とは比例していません。また簡単な問題が高配分のケースもありました。

留意しておくと良いこと

誤訳がある

試験中は問題文の言語を切り替えることができますが、ある問題で、名前空間の指定が原文と日本語で異なるものがありました。翻訳のほうが正しいということはないでしょうから、念のため、日本語を読んだ後で原文もざっと確認しておくのが良さそうです。

デスクの整理

私は普段テレワークで作業している部屋で受験しました。ごちゃごちゃと物が置いてありますが、少し片づけをすれば問題ありませんでした。紙類やペン、書籍、端末類はNGです。壁や見える範囲に文字が書かれたものがあれば隠しましょう。それ以外は比較的ゆるかった印象で、まずそうなものは紙や布で覆っておけば大丈夫でした。

透明なラベルなしのペットボトル水はOK、という情報をどこかで見ましたが、ラベルなしのグラスに水を入れて置いていたところ、片づけるように言われました。

試験官の当たりはずれ

日本語で受験をしましたが、基本的に試験官は日本語ネイティブではないようです。それでも一回目の試験官はスムースに進みましたが、二回目はひどかったです。中国語でメッセージを送ってきたり、翻訳ツールを通しただけの意味の通らないメッセージを送ってきたりしました。またそのためか非常に時間がかかり、開始から実際に試験を開始できるまでに30分を要しました。普通に英語が読めるのでしたら、英語で受験したほうが良いかもしれません。

所感

想定していたとはいえ、認定試験に落ちたのは久しぶりでした。難しかったですが、おかげでかなり力がついたと思います。

読み物だけで合格することはほぼ不可能です。業務で利用しているか、慣れるための環境を自分で用意しないと厳しいです。その意味で、教材としてすぐに触れる環境があることが大事です。Udemyのように実行環境がついてくる講座を利用するか、メガクラウドの無料枠を駆使して安いVMで構築しておき、勉強期間中は落とし上げして利用するかのどちらかだと思います。

小手先で合格できてしまうような試験も多いですが、CKAには当てはまりません。地道に実践的な勉強をするのが近道です。こういう試験が認定試験のあるべき姿だと思いました。