GCP Associate Cloud Engineerに合格しました

はじめに

2021年9月に転職してからGCPを業務で使用することになりました。

筆者の技術レベル

  • アプリ開発AWSを1年ほど触っていた (資格は持っていない)
  • GCPは2021年12月に受けた時点で経験3ヶ月
  • kubernetesはkindやminikubeで触ったことがあるレベル

対策

主に試験対策として勉強したことはUdemyの問題集だけです。

問題集はテスト1つあたり4 ~ 5周して90%以上にしてから望みました。

  1. 【GCP認定資格】Google Cloud Platform Associate Cloud Engineer模擬問題集 | Udemy

  2. Google Cloud Associate Cloud Engineer Practice Test 2021 | Udemy

試験前日

sentinelというアプリをインストールしました

試験当日

当日はレンタルスペースを試験開始時間30分前から3時間借りてオンラインで受けました

持っていったものは

です

開始前

Webassessorというサイトでアカウントを作成する必要があるのですが、名前を漢字で入力したので身分証明書として運転免許証を使いました

最初、試験監督者は英語でチャットしてくるのですが本人確認するときに運転免許証を提示すると日本語で対応してくれるようになりました

部屋をカメラで映す必要があるので、Mac Bookを手に持って部屋の周り、天井、床をそれぞれ5秒ずつ映すと"もう大丈夫"と言われました

そしてMac Bookと充電コードを映すように言われスマホで写真をとって見せ、最後にPCの全面を見せてくれと言われるのでそれもスマホで写真を撮って見せると確認が終わったらしく、試験がスタートしました

試験中

Udemyでやったところが6 ~ 7割ぐらい出てきたのでそれほど難しくなく30 ~ 40分で回答を終え、15分ぐらいゆっくり見直しをしました

試験終了

最後にアンケートの回答をして合格と表示されていました

所感

他の合格された方の勉強方法を調べましたが、もし実務でGCPを触っているならばAssociateの段階で

  • Coursera
  • Qwiklabs
  • 公式模擬試験

をする必要ないと感じました

奇跡的に当日のトラブルがなかったので、安心しました
この記事以外にも他の方が注意点やトラブルについて書かれているのでそちらを参考にしたほうがいいと思います

この記事で伝えたかったこと

  • 運転免許証でも本人確認できる
  • オンライン受験はノートPCとスマホと運転免許証で受けられる
  • AssociateならUdemyの問題集だけでほとんどカバーできる

です!

参考になれば幸いです

Argo CD NotificationsでSlackに通知をしてみる

はじめに

  • argocd notificationsに興味があったので構築手順をブログに残します

対象

  • argocd-notificationsを触ってみたいが、開発環境の構築方法がわからない人
  • 手元の環境でargocd-notificationsを触ってみたい人

目標

guestbookアプリをSyncしたときSlackに通知される

f:id:kntks:20210822095907p:plain

前提

  • docker, kind, kustomizationがインストールされている

前準備

ディレクトリ構成は下の記事で紹介したここと同じものを準備します

全てコピーしてくるとディレクトリは以下のようになっていると思います
ktbbrk.hatenablog.com

※ 使わないディレクトリは削除しています

$ tree
.
└── manifests
    └── argocd
        ├── base
        │   ├── kustomization.yaml
        │   └── namespace.yaml
        └── overlays
            └── development
                ├── apps
                │   └── guestbook.yaml
                └── kustomization.yaml

Argo CDを立ち上げる

$ kustomize build manifests/argocd/overlays/development | k apply -f -

$ k -n argocd get secret argocd-initial-admin-secret -o jsonpath='{.data.password}' | base64 -d

$ k port-forward svc/argocd-server -n argocd 8080:443

http://localhost:8080 にアクセスします

guestbookのApplicationを作成する

$  k apply -f manifests/argocd/overlays/development/apps/guestbook.yaml

前準備を全て行うと以下の画像のようになっているはずです

f:id:kntks:20210822152443p:plain

Slackでappを作成する

以下のサイトにApp作成の手順が書いてあるので、1 ~ 5までを行ってください

argocd-notifications.readthedocs.io

tokenが取得できるのでどこかにメモしておきましょう

Secretを作成する

slackからtokenを取得したらSecretを作成します

manifests/argocd/base/argocd-notifications-secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: argocd-notifications-secret
stringData:
  slack-token: xoxb-xxxxxxxx

ConfigMapを作成する

以下のコマンドでTriggerとTemplateの設定をダウンロードします

curl -o  manifests/argocd/base/argocd-notifications-cm.yaml  https://raw.githubusercontent.com/argoproj-labs/argocd-notifications/v1.1.1/catalog/install.yaml

argocd-notifications-cm.yamlを編集します

data:
  # 以下を追加
  service.slack: |
    token: $slack-token

# ~~  省略  ~~~~

kustomization.yamlを編集する

manifests/argocd/base/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: argocd
resources:
- https://raw.githubusercontent.com/argoproj-labs/argocd-notifications/v1.1.1/manifests/install.yaml
- ./namespace.yaml

patchesStrategicMerge:
- ./argocd-notifications-secret.yaml
- ./argocd-notifications-cm.yaml

ディレクトリの確認

 $ tree
.
└── manifests
    └── argocd
        ├── base
        │   ├── argocd-notifications-cm.yaml
        │   ├── argocd-notifications-secret.yaml
        │   ├── kustomization.yaml
        │   └── namespace.yaml
        └── overlays
            └── development
                ├── apps
                │   └── guestbook.yaml
                └── kustomization.yaml

argocd-notificationのインストールと一緒にkustomize buildする

$ kustomize build manifests/argocd/overlays/development/ | k apply -f -

Argo CDのApplicationにannotationをつける

今回slackのチャンネル名は generalを指定します

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
  # 以下のannotatioinsを追加
  annotations:
    notifications.argoproj.io/subscribe.on-sync-succeeded.slack: general
spec:
  project: default
  source:
    repoURL: https://github.com/argoproj/argocd-example-apps.git
    targetRevision: HEAD
    path: guestbook
  destination:
    server: https://kubernetes.default.svc
    namespace: default

結果を反映する

$ k apply -f manifests/argocd/overlays/development/apps/guestbook.yaml

Slackに通知する

Syncボタンを押してみましょう f:id:kntks:20210822194052p:plain

Slackから通知が来ると思います f:id:kntks:20210822200513p:plain

ログを確認する

argocd-notifications-controller-xxxの名前を探す

$ k -n argocd get pod
NAME                                               READY   STATUS    RESTARTS   AGE
argocd-application-controller-0                    1/1     Running   0          4h54m
argocd-dex-server-68c7bf5fdd-qvqnx                 1/1     Running   0          4h54m
argocd-notifications-controller-7df59c88f8-sct8s   1/1     Running   0          43m

$ k -n argocd logs -f argocd-notifications-controller-7df59c88f8-sct8s

controllerに登録したTemplateを確認する

もしslackに通知が来ない場合はTemplateが登録されていない可能性がある

$ k exec -it -n argocd argocd-notifications-controller-7df59c88f8-sct8s  -- /app/argocd-notifications trigger get

最後に

今回使用したコードはここにまとめています

参考

Argo CD Notifications

Slack - Argo CD Notifications

Troubleshooting - Argo CD Notifications

kind + Kustomization + Argo CDのローカル環境を作成する

はじめに

kubernetesを使用するにあたって色々なツールを学ぶ必要があると思っています

今回はCD toolとして名前の挙がるArgo CDを触ってみようと思います

対象

  • kubernetesを触ってみたいが何をしていいのかわからない人
  • Argo CDを初めて触る人

目標

前提

  • dockerをPCにインストールしている
  • kind, kustomizeをローカルで使用できる

前準備

kindでclusterを作成する

$ kind create cluster --name argocd
Creating cluster "argocd" ...
 ✓ Ensuring node image (kindest/node:v1.21.1) 🖼
 ✓ Preparing nodes 📦
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
Set kubectl context to "kind-argocd"
You can now use your cluster with:

kubectl cluster-info --context kind-argocd

Have a nice day! 👋

contextを確認する

alias k=kubectlとしてエイリアスを付けています

$ k config get-contexts
CURRENT   NAME             CLUSTER          AUTHINFO         NAMESPACE
*         kind-argocd      kind-argocd      kind-argocd

ディレクトリを作成する

今回は以下のようにディレクトリを作成します

 $ tree
.
└── manifests
    ├── apps
    └── argocd
        ├── base
        └── overlays
            ├── development
            │   └── apps
            ├── production
            └── staging

トップのディレクトリからmanifestsを作成したのは、以下のようにIaCで定義したリソースも同一リポジトリで管理できるように考慮したためです

.
├── cdk
├── manifests
└── terraform

ちなみに今回は使用しませんがmanifests/appsは各マイクロサービスのリソースを定義する場所を想定しています

.
└── manifests
    └── apps
        └── hoge-api
            └── deployment.yaml

Argo CDをインストール

Getting Startedではコマンドを入力するようにしていますが、今回はyamlの定義を書いてapplyします

namespaceの追加

manifests/argocd/base/namespace.yaml

apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: null
  name: argocd
spec: {}
status: {}

kustomization yamlの追加

manifests/argocd/base/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: argocd
resources:
- ./namespace.yaml
patchesStrategicMerge:

manifests/argocd/overlays/development/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: argocd
resources:
- ../../base/namespace.yaml
- github.com/argoproj/argo-cd/manifests/cluster-install?ref=v2.0.5
patchesStrategicMerge:

ディレクトリ確認

現在のディレクトリとファイルは以下のようになっているはずです

.
└── manifests
    ├── apps
    └── argocd
        ├── base
        │   ├── kustomization.yaml
        │   └── namespace.yaml
        └── overlays
            ├── development
            │   ├── apps
            │   └── kustomization.yaml
            ├── production
            └── staging

applyを実行してArgo CDをインストールする

$ kustomize build manifests/argocd/overlays/development/ | k apply -f -

リソースの確認

$ k get all -n argocd

Argo CDにログインする

ブラウザでアクセスする

port forwardingでブラウザからアクセスできるようにします

k port-forward svc/argocd-server -n argocd 8080:443

ブラウザから http://localhost:8080 にアクセスしてみましょう

パスワードを取得する

 $ k -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

以下の情報でログインする

Username: admin
Password: <先ほど取得したパスワード>

f:id:kntks:20210818170139p:plain

guest bookのAppを作成する

Creating Apps Via UIでもAppを作成することができますが、ここもyamlで定義を書いてapplyしようと思います

yamlの定義

ここからyamlの定義を取ってきます

しかし、namespaceがguestbookになっているので、今回はnamespaceをdefaultに変更します

manifests/argocd/overlays/development/apps/guestbook.yaml

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/argoproj/argocd-example-apps.git
    targetRevision: HEAD
    path: guestbook
  destination:
    server: https://kubernetes.default.svc
    namespace: default  # ←ここを変更する

yamlをapplyする

$ k apply -f manifests/argocd/overlays/development/apps/guestbook.yaml

f:id:kntks:20210820151750p:plain

syncボタンを押すとSync OKになります

f:id:kntks:20210820151949p:plain

リソースの確認

$ k get all
NAME                                READY   STATUS    RESTARTS   AGE
pod/guestbook-ui-85985d774c-sblqh   1/1     Running   0          4m59s

NAME                   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/guestbook-ui   ClusterIP   10.96.24.143   <none>        80/TCP    5m
service/kubernetes     ClusterIP   10.96.0.1      <none>        443/TCP   2d2h

NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/guestbook-ui   1/1     1            1           4m59s

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/guestbook-ui-85985d774c   1         1         1       4m59s

ブラウザでguest bookを表示する

$ k get svc
NAME           TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
guestbook-ui   ClusterIP   10.96.24.143   <none>        80/TCP    9m58s

$ k port-forward svc/guestbook-ui 8000:80

http://localhost:8000 にアクセスするとguestbookが表示されます

f:id:kntks:20210820152902p:plain

最後に

今回使用したファイルはここにあります

参考

Amazon EKSでのArgoCDを使ったGitOps CD – PSYENCE:MEDIA

Declarative Setup - Argo CD - Declarative GitOps CD for Kubernetes

golang + ElasticSearch(docker)を触ってみる

はじめに

検索機能をelastic searchを使って実装したいけど、何ができるかわからないし、どうやって実装して良いのかもわからなかったので golangとelastic searchで簡単な実装をしてみようと思います

対象

  • golang + elastic searchに興味がある人、初めて触る人

環境

ツール バージョン
go 1.16.3
docker Engine 20.10.6
docker compose 1.29.1

コンテナを立ち上げる

docker-compose.yml

version: "3.8"

services: 
   es:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.13.1
    container_name: elasticsearch
    environment:
      - discovery.type=single-node
    volumes:
      - ./es/data:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
      - 9300:9300

docker-compose up

参考: Install Elasticsearch with Docker | Elasticsearch Guide [7.13] | Elastic

Infoを取得してみる

まずはREADMEに書いてあるUsageを参考にコードを書いていきます

func GetInfo() {
    es, err := elasticsearch.NewDefaultClient()
    if err != nil {
        log.Fatal(err)
    }
    res, err := es.Info()
    if err != nil {
        log.Fatal(err)
    }
    defer res.Body.Close()
    var r map[string]interface{}
    if err := json.NewDecoder(res.Body).Decode(&r); err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%+v\n", r)
}

output

map[cluster_name:docker-cluster cluster_uuid:T38_LnjTS_aBtlDa1lMZIA name:0cdf44e15374 tagline:You Know, for Search version:map[build_date:2021-05-28T17:40:59.346932922Z build_flavor:default build_hash:9a7758028e4ea59bcab41c12004603c5a7dd84a9 build_snapshot:false build_type:docker lucene_version:8.8.2 minimum_index_compatibility_version:6.0.0-beta1 minimum_wire_compatibility_version:6.8.0 number:7.13.1]]

Q, elastic searchのURLなど指定していないけど、なぜアクセスできるのか
A, 何も指定していない時はhttp://localhost:9200が使用されるから

// NewDefaultClient creates a new client with default options.
// It will use http://localhost:9200 as the default address.
// It will use the ELASTICSEARCH_URL environment variable, if set,
// to configure the addresses; use a comma to separate multiple URLs.

go-elasticsearch/elasticsearch.go at master · elastic/go-elasticsearch · GitHub

データをpostしてみる

func ExampleRequest() {
    es, err := elasticsearch.NewDefaultClient()
    if err != nil {
        log.Fatal(err)
    }

    req := esapi.IndexRequest{
        Index:      "test",
        DocumentID: strconv.Itoa(1),
        Body:       strings.NewReader(`{"test": "hogehoge"}`),
    }

    res, err := req.Do(context.Background(), es)
    if err != nil {
        log.Fatal(err)
    }
    defer res.Body.Close()
    if res.IsError() {
        log.Fatalf("failed to request %+v\n", res)
    }
    var r map[string]interface{}
    if err := json.NewDecoder(res.Body).Decode(&r); err != nil {
        log.Fatalf("Error parsing the response body: %s", err)
    }
    log.Printf("[%s] %s; version=%d", res.Status(), r["result"], int(r["_version"].(float64)))
}

output

[201 Created] created; version=1

データを取得してみる

func ExampleSearch() {
    es, err := elasticsearch.NewDefaultClient()
    if err != nil {
        log.Fatal(err)
    }

    var buf bytes.Buffer
    query := map[string]interface{}{
        "query": map[string]interface{}{
            "match": map[string]interface{}{
                "test": "hogehoge",
            },
        },
    }
    if err := json.NewEncoder(&buf).Encode(query); err != nil {
        log.Fatalf("Error encoding query: %s", err)
    }
    res, err := es.Search(
        es.Search.WithContext(context.Background()),
        es.Search.WithIndex("test"),
        es.Search.WithBody(&buf),
        es.Search.WithTrackTotalHits(true),
        es.Search.WithPretty(),
    )
    if err != nil {
        log.Fatalf("Error getting response: %s", err)
    }
    defer res.Body.Close()
    if res.IsError() {
        var e map[string]interface{}
        if err := json.NewDecoder(res.Body).Decode(&e); err != nil {
            log.Fatalf("Error parsing the response body: %s", err)
        }
        // Print the response status and error information.
        log.Fatalf("[%s] %s: %s",
            res.Status(),
            e["error"].(map[string]interface{})["type"],
            e["error"].(map[string]interface{})["reason"],
        )
    }

    var r map[string]interface{}
    if err := json.NewDecoder(res.Body).Decode(&r); err != nil {
        log.Fatalf("Error parsing the response body: %s", err)
    }

    fmt.Printf("%v\n", r)

    log.Printf(
        "[%s] %d hits; took: %dms",
        res.Status(),
        int(r["hits"].(map[string]interface{})["total"].(map[string]interface{})["value"].(float64)),
        int(r["took"].(float64)),
    )

    for _, hit := range r["hits"].(map[string]interface{})["hits"].([]interface{}) {
        log.Printf(" * ID=%s, %s", hit.(map[string]interface{})["_id"], hit.(map[string]interface{})["_source"])
    }
}

output

map[_shards:map[failed:0 skipped:0 successful:1 total:1] hits:map[hits:[map[_id:1 _index:test _score:0.2876821 _source:map[test:hogehoge] _type:_doc]] max_score:0.2876821 total:map[relation:eq value:1]] timed_out:false took:3]
2021/06/06 20:09:59 [200 OK] 1 hits; took: 3ms
2021/06/06 20:09:59  * ID=1, map[test:hogehoge]

まとめ

ほとんどREADMEのUsageに書いてあるコードを使用しました
環境構築やgo-elasticsearchの使い方がわからないと言う人が多いと思うので、この記事を参考に導入の手助けになればと思います

aws ecs & Fargateでhelloを表示する

はじめに

ECSの勉強したいけど何したらいいのかわからないという方は多いと思います

僕自身も絶賛勉強中なので備忘録としてECSの設定手順をまとめます

対象者

  • ECS何もわからんけど興味あるひと
  • お金に多少の余裕があるひと

<注> fargateは時間に対して料金がかかる

料金 - AWS Fargate | AWS

前提条件

  • dockerのコマンドがわかる
  • AWSアカウントを持っている

1, コンテナイメージを用意しよう

今回はgolangのイメージを用意します

使用するファイル

multistage-buildを使ってイメージサイズを落とした方が良いですが、ここでは割愛します

Dockerfile

FROM golang:alpine

COPY main.go /go/src
WORKDIR /go/src
CMD [ "go", "run", "main.go" ]

main.go

package main

import (
    "fmt"
    "log"
    "net/http"
    "time"
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, "hello")
    })

    srv := &http.Server{
        Handler:           mux,
        Addr:              ":8000",
        ReadHeaderTimeout: 15 * time.Second,
        WriteTimeout:      15 * time.Second,
    }

    log.Fatal(srv.ListenAndServe())
}

イメージのビルド

docker build -t test-server .

ローカル環境でコンテナを実行する

docker run -it --rm -p 8000:8000 test-server

ターミナルでcurlをすると"hello"が出ると思います

$ curl http://localhost:8000/hello
hello

2, ECR (Elastic Container Registry)にイメージをpushする

リポジトリを作成を押す f:id:kntks:20210321202710p:plain

今回は test-repositoryという名前のリポジトリを作成します
それ以外はデフォルトでOK
f:id:kntks:20210321202850p:plain

リポジトリ作成後 プッシュコマンドの表示をクリック

f:id:kntks:20210321202938p:plain

プッシュコマンドが表示されるので、これを自分のターミナルに入力します

f:id:kntks:20210321204602p:plain

# Dockerクライアント認証
$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com
Login Succeeded

# docker imageの作成
$ docker build -t test-repository .
[+] Building 0.4s (8/8) FINISHED
 => [internal] load build definition from Dockerfile
~~~

# イメージにタグをつける
docker tag test-repository:latest xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/test-repository:latest

# イメージのプッシュ
$ docker push xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/test-repository:latest

再度 リポジトリのコンソールを見るとイメージがアップされているのが確認できると思います

f:id:kntks:20210321205543p:plain

3, ECSでクラスターを作成しよう

クラスターの作成をクリック f:id:kntks:20210321220137p:plain

ネットワーキングのみを選択

f:id:kntks:20210321220330p:plain

クラスター名は任意でいれる、今回は新規にVPCを作成

f:id:kntks:20210321220510p:plain

これでクラスターの作成は完了

f:id:kntks:20210321223327p:plain

4, タスクを定義しよう

新しいタスク定義の作成

f:id:kntks:20210321225014p:plain

起動タイプの互換性の選択ではFargateを選択します

f:id:kntks:20210321225102p:plain

f:id:kntks:20210321234830p:plainf:id:kntks:20210321234830p:plain

4, タスクを実行しよう

f:id:kntks:20210322003617p:plain

f:id:kntks:20210322003725p:plain

タスクが完了したらパブリックIPを確認しましょう

(訳あってタスク定義を作り直し直したので、名前が少し変わりました)

f:id:kntks:20210322011142p:plain

セキュリティグループのポート開け忘れに注意
しかし、後から変更できるので設定ミスしても問題はありません

 $ curl http://<ipアドレス>:8000/hello
hello

aws-cdkをupdateしようとするとversionが上がらず、なぜかnpmが消える

現象

aws-cdkのバージョンを1.71.0から1.93.0に上げようとコマンドを入力しても何も起こりませんでした

しかもなぜかnpmが消えるという現象に・・

~ $ cdk --version
1.71.0 (build 953bc25)
~ $ npm update -g aws-cdk

removed 253 packages, and audited 1 package in 1s

found 0 vulnerabilities

~ $ which npm
~ $

npmを再インストール

reinstallコマンド入力するとnpmが復活します

~ $ brew reinstall node

原因

どうやらyarnのグローバルに入っていたのが原因?っぽいです

~ $ ls -l `which cdk`
lrwxr-xr-x  1 user-name  admin  64 11  1 14:40 /usr/local/bin/cdk -> ../../../Users/user-name/.config/yarn/global/node_modules/.bin/cdk

解決策

まずは yarnをグローバル環境から削除して

~ $ yarn global remove aws-cdk
yarn global v1.22.10
warning package.json: No license field
[1/2] 🗑  Removing module aws-cdk...
[2/2] 🔨  Regenerating lockfile and installing missing dependencies...
success Uninstalled packages.
✨  Done in 2.42s.

再度cdkをインストール

~ $ npm i -g aws-cdk

added 193 packages, and audited 194 packages in 14s

found 0 vulnerabilities

最後に確認

~ $ ls -l `which cdk`
lrwxr-xr-x  1 user-name  admin  35  3 15 00:06 /usr/local/bin/cdk -> ../lib/node_modules/aws-cdk/bin/cdk

これで直りました

aws-cdk(Typescript) error :Argument of type 'xx' is not assignable to parameter of type 'IConstruct'. Types of property 'node' are incompatible.

はじめに

そこのあなた! もしかして、aws-cdkで型はあっているのに下のエラーメッセージが出てきてお困りではありませんか?

Type 'import("/<ディレクトリまでのパス>/node_modules/@aws-cdk/aws-iam/node_modules/@aws-cdk/core/lib/construct-compat").ConstructNode' is not assignable to type 'import("/<ディレクトリまでのパス>/node_modules/@aws-cdk/core/lib/construct-compat").ConstructNode'.
Types have separate declarations of a private property 'host'.

この記事では、原因の確認方法とその解決策を紹介します。


環境

$ cdk --version
1.88.0 (build f65009b)

原因

cdk関連でインストールしたモジュールの全てのバージョンが一致していないと発生するようです。

github.com


確認

方法1:

先ほどの原因の部分でもお伝えしたように、まずはじめにpackage.json@aws-cdk/xxx のバージョンが全て同じか確認しましょう

例えば、以下のようにバージョンが一つでも違う場合は発生する可能性があります

 "dependencies": {
     "@aws-cdk/assert": "1.88.0",
     "@aws-cdk/aws-ec2": "1.85.0",
     "@aws-cdk/aws-elasticloadbalancingv2": "1.82.0",
     "@aws-cdk/aws-elasticloadbalancingv2-targets": "1.79.0",

github.com

方法2:

package.jsonでバージョンを揃えたのに解消されない・・?

次はdependenciesごとに設定したバージョンになっているか確認してみましょう

  • 作業しているディレクトリに cd
  • 次に以下のコードを入力する。複数のバージョンがインストールされているか確認する
$ cat node_modules/\@aws-cdk/*/package.json | grep version | sort | uniq
"version": "1.88.0",
"version": "1.89.0",

もしバージョンの違うdependenciesを知りたい場合、以下のコマンドを入力する

 $ cat node_modules/\@aws-cdk/*/package.json | grep -B1 "\"version\": \"1.89.0\""
    "name": "@aws-cdk/cloud-assembly-schema",
      "version": "1.89.0",
    --
      "name": "@aws-cdk/core",
      "version": "1.89.0",
    --
      "name": "@aws-cdk/cx-api",
      "version": "1.89.0",
    --
      "name": "@aws-cdk/region-info",
      "version": "1.89.0",

解決方法

  • node_modules/\@aws-cdkpackage-lock.jsonを削除
  • npm install

それではやってみましょう

$ rm package-lock.json
$ rm -r node_modules/\@aws-cdk/
$ npm install

added 32 packages, and audited 660 packages in 17s

$ cat node_modules/\@aws-cdk/*/package.json | grep version | sort | uniq
  "version": "1.88.0",

$ cdk synth
Resources:
  vpcA2121C38:
    Type: AWS::EC2::VPC

まとめ

cdkのバージョンアップのサイクルが早いので、このエラーに遭遇する確率は高いです。

なので、この記事でエラーに躓く人が一人でも減ったらと思います