It's a peacehell world.

こんな名前ですが情報技術について主に扱うブログです。

[kubernetes][Secret] kubernetes の Secret を使って credentials を Pod にマウントする

credentials を秘匿しながら Pod にマウントしよう。

🤔 kubernetes の Secret とは?

まず kubernetes には ConfigMapSecret と、Pod に値を渡すための役割として似たようなものが2種類あります。

公式の ConfigMap の注意書きにも

注意: ConfigMapは機密性や暗号化を提供しません。保存したいデータが機密情報である場合は、ConfigMapの代わりにSecretを使用するか、追加の(サードパーティー)ツールを使用してデータが非公開になるようにしてください。

と記載されているので、

と使い分けたいところです。

🔍 ConfigMap と Secret の違い

kubernetes.io

に書いてあるとおりですが、

  • Secret は dataフィールドのすべてのキーの値は base64エンコードされた文字列である必要がある
  • Secret は tmpfs に保存されるのでディスクストレージに書き込まれない
    • 復元のリスクが少ない(と思われる)

機密情報を Secret にする根拠としては「tmpfs に保存されるのでディスクストレージに書き込まれない」からですかね〜。(base64 は根拠にならないよね)

📜 Secret を使って credentials を Pod にマウントする

ようやく本題です。

まずは手元の credentials.json をもとに Secret を作成します。

$ kubectl create secret generic {Secret名} --from-file={podに配置するファイル名}={credentials.json格納先}

# 例
$ kubectl create secret generic my-credentials --from-file=credentials.json=/home/test-user/credentials.json

次に Pod から Secret を参照します。

マニフェストファイルは以下のような形になります。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      volumes:
      - name: my-key
        secret:
          secretName: my-credentials
      containers:
      - image: nginx
        name: sample-pod
        ports:
        - containerPort: 80
        volumeMounts:
        - name: my-key
          mountPath: /var/secret/

Secret 作成時の kubectl create secret generic {Secret名} で設定した Secret名 を secretName: の値として設定します。

mountPath が credentials の格納先ですね。

kubectl apply -f {マニフェストファイル} で起動して Pod の中に入って mountPath で指定したパスを確認すると credentials が格納されていることを確認できます。

おわりに

ConfigMap と Secret についてはなんとなく使える状態まで仕上がりました。

kubernetes 大変ですが、やってて損はないと信じて今後も頑張りましょう。💪

[soccer-cli] ターミナルで海外サッカーの試合結果を確認しよう

記事数稼ぐためにツール紹介の小ネタでお茶を濁します。

はじめに

クリスティアーノ・ロナウドマンチェスター・ユナイテッド復帰、セリエ A 昨シーズン MVP ロメル・ルカクチェルシー復帰、冨安健洋選手のアーセナル移籍など、今シーズンもプレミアリーグから目が離せませんね。

さて、皆さんターミナルでサッカーの試合結果や順位を確認したくなることありますよね?

そんなときにおすすめしたいのが soccer-cli です。

早速ターミナルで我らがチェルシーの試合結果と順位を確認してみましょう。

🎸 余談

OASIS ノエル・ギャラガー氏によるとチェルシーファンは人間以下のクズどもとのことです。😇

f:id:ghostzapper:20211115182637j:plain

⌨️ 環境

  • MacOS Big Sur 11.4
  • git version 2.32.0
  • Python 3.9.0
  • 動作確認日:2021-11-19

API トークン取得

football-data.orgAPI token を取得する必要があります。

こちらから名前とメールアドレスを入力して登録すると「Your free API-key for football-data.org」の件名のメールが届き、本文に

Your API token: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

と記載されています。

soccer-cli インストール

soccer-cli の Build from source に従い soccer-cli をインストールします。

$ git clone https://github.com/architv/soccer-cli.git
$ cd soccer-cli
$ python setup.py install

⚽️ 使う

我らがチェルシーの試合結果と現在の順位を確認してみます。

まず、対象チームの試合結果を確認するには --team オプションでチームを指定します。

しかし、--team で指定するチームコードがわからないので、soccer --list でチームコードを確認してみます。

$ soccer --list
...(プレミアリーグ以外も出力されますが割愛します)
Premier League
AFC: Arsenal FC
AFCB: AFC Bournemouth
AVFC: Aston Villa FC
CFC: Chelsea FC
CRY: Crystal Palace FC
EFC: Everton FC
LCFC: Leicester City FC
LFC: Liverpool FC
MCFC: Manchester City FC
MUFC: Manchester United FC
NCFC: Norwich City FC
NUFC: Newcastle United FC
SCFC: Stoke City FC
SFC: Southampton FC
SUN: Sunderland AFC
SWA: Swansea City FC
THFC: Tottenham Hotspur FC
WAT: Watford FC
WBA: West Bromwich Albion FC
WHU: West Ham United FC
...(プレミアリーグ以外も出力されますが割愛します)

我らがチェルシーのチームコードは CFC であることがわかりました。

soccer --team CFC で試合結果を確認してみます。

初回実行時は API token の入力を求められるので、先程取得した API token を設定します。

(なお、ここで設定した API token は ~/.soccer-cli.ini で保持されるようです。)

$ soccer --team CFC
No API key found!
Please visit http://api.football-data.org/v2/ and get an API token.
Enter API key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2021-08-14  Chelsea FC                  3  vs  0          Crystal Palace FC
2021-08-22  Arsenal FC                  0  vs  2                 Chelsea FC
2021-08-28  Liverpool FC                1  vs  1                 Chelsea FC
2021-09-11  Chelsea FC                  3  vs  0             Aston Villa FC
2021-09-14  Chelsea FC                  1  vs  0  FK Zenit Sankt-Petersburg
2021-09-19  Tottenham Hotspur FC        0  vs  3                 Chelsea FC
2021-09-25  Chelsea FC                  0  vs  1         Manchester City FC
2021-09-29  Juventus FC                 1  vs  0                 Chelsea FC
2021-10-02  Chelsea FC                  3  vs  1             Southampton FC
2021-10-16  Brentford FC                0  vs  1                 Chelsea FC
2021-10-20  Chelsea FC                  4  vs  0                   Malmö FF
2021-10-23  Chelsea FC                  7  vs  0            Norwich City FC
2021-10-30  Newcastle United FC         0  vs  3                 Chelsea FC
2021-11-02  Malmö FF                    0  vs  1                 Chelsea FC
2021-11-06  Chelsea FC                  1  vs  1                 Burnley FC

今シーズンのチェルシーの試合結果の一覧が取得できました。

マンチェスター・シティに悔しい敗戦を喫しましたが、リーグ戦はその後は無敗です。

さて、気になる順位は…

$ soccer --standings --league=PL
POS     CLUB                              PLAYED        GOAL DIFF     POINTS    
1       Chelsea FC                        11            23            26
2       Manchester City FC                11            16            23
3       West Ham United FC                11            10            23
4       Liverpool FC                      11            20            22
5       Arsenal FC                        11            0             20
6       Manchester United FC              11            2             17
7       Brighton & Hove Albion FC         11            0             17
8       Wolverhampton Wanderers FC        11           -1             16
9       Tottenham Hotspur FC              11           -7             16
10      Crystal Palace FC                 11            1             15
11      Everton FC                        11            0             15
12      Leicester City FC                 11           -2             15
13      Southampton FC                    11           -2             14
14      Brentford FC                      11           -1             12
15      Leeds United FC                   11           -7             11
16      Aston Villa FC                    11           -6             10
17      Watford FC                        11           -7             10
18      Burnley FC                        11           -6             8
19      Newcastle United FC               11           -12            5
20      Norwich City FC                   11           -21            5

11月19日現在チェルシープレミアリーグ1位です!!!🎉🎉🎉

おわりに

これでターミナルから試合結果を確認できるようになりました。

基本的にリアルタイム観戦、FotMob等のアプリ、Twitter で試合結果を確認することが多いと思いますが、ターミナルで贔屓チームの試合結果や順位をみてモチベーションをあげる際には soccer-cli を活用してみてください。

[kubernetes] Error registering network: failed to acquire lease: node "ノード名" pod cidr not assigned

flannel のエラー解消についてメモ残しておきます。

事象

kube-flannel が CrashLoopBackOff になるので、kubectl logs でログを確認すると表題のエラーが出力されていた。

対策

github.com

の通り、/etc/kubernetes/manifests/kube-controller-manager.yaml のコマンドに

  • --allocate-node-cidrs=true
  • --cluster-cidr=10.244.0.0/16

を追加して systemctl restart kubelet 実行することで kube-flannel のステータスが無事に Running になりました。

そもそも、kubeadm init の際に --pod-network-cidr で CIDR を設定していれば問題なかった?

[AWS AppSync] Schema Creation Status is FAILED with details: Internal Failure while saving the schema.

今回は CloudFormation あるあるのエラーメッセージが抽象的でエラーの特定に難航するけど、よくみたら大したこと無いシリーズです。

🔥 事象

AWS AppSync を利用していて、以下のような GraphQL をデプロイすると表題のエラーが発生してデプロイ失敗しました。

CloudFormation では表題のエラーが発生していました。

エラーメッセージと schema.graphql を見ても何が悪いかさっぱりでした。

input UpdatePlayerInput {
  name: String!
  salary: Int!
}

input UpdateTeamInput {
  name: String
  player: [Player!]
}

type Player {
  name: String!
  salary: Int!
}

type Team {
  id: ID!
  name: String
  player: [Player!]
}

💡 原因

当たり前ですが、type では type を設定し、input では input を設定する必要がありました。

今回の場合は Team の player は Player を設定し、UpdateTeamInput の player は UpdatePlayerInput を設定します。

input UpdatePlayerInput {
  name: String!
  salary: Int!
}

input UpdateTeamInput {
  name: String
  player: [UpdatePlayerInput!]
}

type Player {
  name: String!
  salary: Int!
}

type Team {
  id: ID!
  name: String
  player: [Player!]
}

デプロイしたときのエラーメッセージが不親切で原因解明に時間がかかってしまいましたが、こんな当たり前のことだったんですね!

ちなみに

AWS AppSync Console 画面で graphql を入力するとリアルタイムでバリデーションしてくれるぞ!👍

NG f:id:ghostzapper:20211027210940p:plain

Expected [Player!] to be a GraphQL input type.

この気の利いたエラーメッセージを CloudFormation に出してくれませんかね…。

OK f:id:ghostzapper:20211027211213p:plain

まとめ

ということで、GraphQL の静的チェックできていれば Schema Creation Status is FAILED は発生しない(はず)。

AWS AppSync Console 画面が便利なことがわかりましたが、いちいちコンソール開かずにチェックできるよう VS Code Extension でなんかいいのないですかね〜。

[AWS] Lambda で S3 バケットに対する権限を CDK Python で付与したい

はじめに

Lambda から S3 バケットに対して Read/Write したいけどバケットを Public にするわけにはいかない。

そんなときはバケットポリシーで特定の Lambda に対してのみ Read/Write 権限を付与しましょう。

CDK Python でやるときはこんな感じになります。

サンプル

from aws_cdk import (core,
                     aws_s3,
                     aws_iam,
                     )
from aws_cdk.aws_lambda import Runtime
from aws_cdk.aws_lambda_python import PythonFunction


class SampleStack(core.Stack):

    def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # lambda
        lambda_ = PythonFunction(
            self, 'SampleLambda',
            runtime=Runtime.PYTHON_3_8,
            entry='src',
            index='sample.py',
            handler='handler')

        # S3
        bucket_ = aws_s3.Bucket(self, 'sample-bucket-name')
        bucket_.add_to_resource_policy(
            aws_iam.PolicyStatement(
                effect=aws_iam.Effect.ALLOW,
                actions=['s3:PutObject', 's3:GetObject'],
                principals=[
                    aws_iam.ArnPrincipal(
                        lambda_.role.role_arn
                    )
                ],
                resources=[
                    bucket_.arn_for_objects('*')
                ]
            )
        )

こちらをデプロイすると S3 のバケットポリシーは以下のようになります。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": ["{Lambda Role ARN}"]
      },
      "Action": ["s3:PutObject", "s3:GetObject"],
      "Resource": "{S3 Bucket ARN}/*"
    }
  ]
}

これで対象の Lambda 以外からは Access Denied を返すようになりました。

サンプルでは Put と Get 両方付与していますが、S3 バケットから読み取りのみ行う Lambda であれば Action には s3:GetObject のみ設定してください。

おわりに

ArnPrincipal を使うことで "AWS": ["{ARN}"] の書き方ができます。

Lambda だけでなく特定ユーザーのみ操作できるようにするといった場合は IAM ユーザー ARN を設定すればよさそうです。

S3 バケット名は全世界でユニークなので公開は極力控えていきましょう。

[VirtualBox] You must specify a machine to start, using the command line.

小ネタですが、VirtualBox 壊れたのかと焦ってしまったので戒めとして残しておきます。

🔥 事象

VirtualBox 起動しよう」

「お、この前使ったからDock にアイコンあるじゃん。」

「ポチッとな(クリック)」

f:id:ghostzapper:20211019100453p:plain

f:id:ghostzapper:20211019100527p:plain

🤦‍♀️

💡 解消方法

なんと、Dock でクリックしていたのは VirtualBox ではなく、VirtualBoxVM でした!!

同じアイコンで別物なのかよ!

🙅‍♀️ クリックすると表題のエラーダイアログが発生します。

f:id:ghostzapper:20211019100751p:plain

🙆‍♀️ クリックすると VirtualBox マネージャーが起動します。

f:id:ghostzapper:20211019100810p:plain

VirtualBox をクリックしたら無事に VirtualBox マネージャーが起動しました。めでたしめでたし。

余談

VirtualBoxVM と間違わないように VirtualBox を Dock のスタメンに追加することにしました。

Google Search Console で「検出 - インデックス未登録」

今回はブログ運営についてです。

状況

Google Search Consoleサイトマップを登録して

「これでブログのアクセス数あがりまっせ〜🙌」

と息巻いてるバカがいたんですけど、カバレッジを見ると

f:id:ghostzapper:20211018190822p:plain

ご覧のように Google 先生に全ページ 除外 されているではありませんか。

除外の内容はというと、 f:id:ghostzapper:20211018192753p:plain

「検出 - インデックス未登録」とのことです。

公式見解

support.google.com

ページは Google により検出されましたが、まだクロールされていません。これは通常、Google が URL をクロールしようとしたものの、サイトへの過負荷が予想されたため、クロールの再スケジュールが必要となった場合です。そのため、レポート上で最終クロール日が空欄になっています。

時間が解決するといったところでしょうか。

しばらく経っても変わらない場合にサイトへの過負荷とやらについて掘り下げていきます。

ちなみに

現在のステータスは 検出 - インデックス未登録 ですが、クロール済み – インデックス未登録 となると、Google 先生から 写す価値なし低品質 サイトの烙印を押されたことになるようです。

頑張って書いていきますのでどうかよろしくおねがいします🙏 > Google 先生