Azure Disk Enclyptionを有効化したOSディスクの拡張
Azure Disk Encryption(ADE)で暗号化されたOSディスクを拡張する手順についてメモ。
前提
- 暗号化された OS ディスクのサイズ変更はサポート外のため自己責任
OS パーティションのサイズは変更できますか? ADE で暗号化された OS ディスクのサイズは現在のところ変更できません。
- 拡張前に必ずバックアップを取得
- ディスクサイズの拡張はできるけど、縮小はできないことに注意
- RHEL 7 (latest miner)を利用
- Azureポータルより事前にOSディスクの暗号化を実施
確認
対象仮想マシンを展開して、既定ではOSディスクサイズが64GiBであることを確認
# df -h Filesystem Size Used Avail Use% Mounted on devtmpfs 3.9G 0 3.9G 0% /dev tmpfs 3.9G 0 3.9G 0% /dev/shm tmpfs 3.9G 9.1M 3.9G 1% /run tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup /dev/mapper/rootvg-rootlv 2.0G 70M 2.0G 4% / /dev/mapper/rootvg-usrlv 10G 1.5G 8.6G 15% /usr /dev/sda2 494M 153M 342M 31% /boot /dev/mapper/rootvg-homelv 1014M 33M 982M 4% /home /dev/mapper/rootvg-optlv 2.0G 140M 1.9G 7% /opt /dev/mapper/rootvg-tmplv 2.0G 33M 2.0G 2% /tmp /dev/sda1 500M 9.9M 490M 2% /boot/efi /dev/mapper/rootvg-varlv 8.0G 185M 7.9G 3% /var /dev/sdb1 16G 45M 15G 1% /mnt /dev/sdc1 42M 1.5K 42M 1% /mnt/azure_bek_disk tmpfs 783M 0 783M 0% /run/user/1000
# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 64G 0 disk ├─sda1 8:1 0 500M 0 part /boot/efi ├─sda2 8:2 0 500M 0 part /boot ├─sda3 8:3 0 2M 0 part └─sda4 8:4 0 63G 0 part └─osencrypt 253:0 0 63G 0 crypt ├─rootvg-tmplv 253:1 0 2G 0 lvm /tmp ├─rootvg-usrlv 253:2 0 10G 0 lvm /usr ├─rootvg-optlv 253:3 0 2G 0 lvm /opt ├─rootvg-homelv 253:4 0 1G 0 lvm /home ├─rootvg-varlv 253:5 0 8G 0 lvm /var └─rootvg-rootlv 253:6 0 2G 0 lvm / sdb 8:16 0 16G 0 disk └─sdb1 8:17 0 16G 0 part /mnt sdc 8:32 0 48M 0 disk └─sdc1 8:33 0 46M 0 part /mnt/azure_bek_disk
ディスクサイズを変更するためAzureポータルより仮想マシンを停止(割り当て解除)し、その後OSディスクを選択して、サイズを変更 (今回は64GiBから128GiBに変更)を実施する。 その後仮想マシンを起動する。
パーティションを拡張する。
# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 128G 0 disk ├─sda1 8:1 0 500M 0 part /boot/efi ├─sda2 8:2 0 500M 0 part /boot ├─sda3 8:3 0 2M 0 part └─sda4 8:4 0 63G 0 part └─osencrypt 253:0 0 63G 0 crypt ├─rootvg-tmplv 253:1 0 2G 0 lvm /tmp ├─rootvg-usrlv 253:2 0 10G 0 lvm /usr ├─rootvg-optlv 253:3 0 2G 0 lvm /opt ├─rootvg-homelv 253:4 0 1G 0 lvm /home ├─rootvg-varlv 253:5 0 8G 0 lvm /var └─rootvg-rootlv 253:6 0 2G 0 lvm / sdb 8:16 0 16G 0 disk └─sdb1 8:17 0 16G 0 part /mnt sdc 8:32 0 48M 0 disk └─sdc1 8:33 0 46M 0 part /mnt/azure_bek_disk # growpart /dev/sda 4 CHANGED: partition=4 start=2054144 old: size=132161536 end=134215680 new: size=266381278 end=268435422 # lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 128G 0 disk ├─sda1 8:1 0 500M 0 part /boot/efi ├─sda2 8:2 0 500M 0 part /boot ├─sda3 8:3 0 2M 0 part └─sda4 8:4 0 127G 0 part └─osencrypt 253:0 0 63G 0 crypt ├─rootvg-tmplv 253:1 0 2G 0 lvm /tmp ├─rootvg-usrlv 253:2 0 10G 0 lvm /usr ├─rootvg-optlv 253:3 0 2G 0 lvm /opt ├─rootvg-homelv 253:4 0 1G 0 lvm /home ├─rootvg-varlv 253:5 0 8G 0 lvm /var └─rootvg-rootlv 253:6 0 2G 0 lvm / sdb 8:16 0 16G 0 disk └─sdb1 8:17 0 16G 0 part /mnt sdc 8:32 0 48M 0 disk └─sdc1 8:33 0 46M 0 part /mnt/azure_bek_disk
暗号化された領域を拡張する。
[root@labrhellvm ~]# cryptsetup resize /dev/mapper/osencrypt [root@labrhellvm ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 128G 0 disk ├─sda1 8:1 0 500M 0 part /boot/efi ├─sda2 8:2 0 500M 0 part /boot ├─sda3 8:3 0 2M 0 part └─sda4 8:4 0 127G 0 part └─osencrypt 253:0 0 63G 0 crypt ├─rootvg-tmplv 253:1 0 2G 0 lvm /tmp ├─rootvg-usrlv 253:2 0 10G 0 lvm /usr ├─rootvg-optlv 253:3 0 2G 0 lvm /opt ├─rootvg-homelv 253:4 0 1G 0 lvm /home ├─rootvg-varlv 253:5 0 8G 0 lvm /var └─rootvg-rootlv 253:6 0 2G 0 lvm / sdb 8:16 0 16G 0 disk └─sdb1 8:17 0 16G 0 part /mnt sdc 8:32 0 48M 0 disk └─sdc1 8:33 0 46M 0 part /mnt/azure_bek_disk [root@labrhellvm ~]# pvs PV VG Fmt Attr PSize PFree /dev/mapper/osencrypt rootvg lvm2 a-- <63.02g <38.02g [root@labrhellvm ~]# pvresize /dev/mapper/osencrypt Physical volume "/dev/mapper/osencrypt" changed 1 physical volume(s) resized or updated / 0 physical volume(s) not resized [root@labrhellvm ~]# pvs PV VG Fmt Attr PSize PFree /dev/mapper/osencrypt rootvg lvm2 a-- <63.02g <38.02g
再起動して反映される確認する。
[root@labrhellvm ~]# pvs PV VG Fmt Attr PSize PFree /dev/mapper/osencrypt rootvg lvm2 a-- <63.02g <38.02g
変わらないので、再度PVを拡張すると、128 GiB まで拡張された。
[root@labrhellvm ~]# pvresize /dev/mapper/osencrypt Physical volume "/dev/mapper/osencrypt" changed 1 physical volume(s) resized or updated / 0 physical volume(s) not resized [root@labrhellvm ~]# pvs PV VG Fmt Attr PSize PFree /dev/mapper/osencrypt rootvg lvm2 a-- <127.02g <102.02g
root ("/") に全振りしてみる。
# lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert homelv rootvg -wi-ao---- 1.00g optlv rootvg -wi-ao---- 2.00g rootlv rootvg -wi-ao---- 2.00g tmplv rootvg -wi-ao---- 2.00g usrlv rootvg -wi-ao---- 10.00g varlv rootvg -wi-ao---- 8.00g # lvextend -l 100%FREE /dev/rootvg/rootlv Size of logical volume rootvg/rootlv changed from 2.00 GiB (512 extents) to <102.02 GiB (26116 extents). Logical volume rootvg/rootlv successfully resized. # lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert homelv rootvg -wi-ao---- 1.00g optlv rootvg -wi-ao---- 2.00g rootlv rootvg -wi-ao---- <102.02g tmplv rootvg -wi-ao---- 2.00g usrlv rootvg -wi-ao---- 10.00g varlv rootvg -wi-ao---- 8.00g
最後に対象LV上のファイルシステムを拡張する。
# df -h Filesystem Size Used Avail Use% Mounted on devtmpfs 3.9G 0 3.9G 0% /dev tmpfs 3.9G 0 3.9G 0% /dev/shm tmpfs 3.9G 9.1M 3.9G 1% /run tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup /dev/mapper/rootvg-rootlv 2.0G 70M 2.0G 4% / /dev/mapper/rootvg-usrlv 10G 1.5G 8.6G 15% /usr /dev/sda2 494M 153M 342M 31% /boot /dev/sda1 500M 9.9M 490M 2% /boot/efi /dev/mapper/rootvg-homelv 1014M 33M 982M 4% /home /dev/mapper/rootvg-tmplv 2.0G 33M 2.0G 2% /tmp /dev/mapper/rootvg-optlv 2.0G 140M 1.9G 7% /opt /dev/mapper/rootvg-varlv 8.0G 186M 7.9G 3% /var /dev/sdb1 16G 45M 15G 1% /mnt /dev/sdc1 42M 1.5K 42M 1% /mnt/azure_bek_disk tmpfs 783M 0 783M 0% /run/user/1000 # xfs_growfs / meta-data=/dev/mapper/rootvg-rootlv isize=512 agcount=4, agsize=131072 blks = sectsz=4096 attr=2, projid32bit=1 = crc=1 finobt=0 spinodes=0 data = bsize=4096 blocks=524288, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0 ftype=1 log =internal bsize=4096 blocks=2560, version=2 = sectsz=4096 sunit=1 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 data blocks changed from 524288 to 26742784 # df -h Filesystem Size Used Avail Use% Mounted on devtmpfs 3.9G 0 3.9G 0% /dev tmpfs 3.9G 0 3.9G 0% /dev/shm tmpfs 3.9G 9.1M 3.9G 1% /run tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup /dev/mapper/rootvg-rootlv 103G 82M 102G 1% / /dev/mapper/rootvg-usrlv 10G 1.5G 8.6G 15% /usr /dev/sda2 494M 153M 342M 31% /boot /dev/sda1 500M 9.9M 490M 2% /boot/efi /dev/mapper/rootvg-homelv 1014M 33M 982M 4% /home /dev/mapper/rootvg-tmplv 2.0G 33M 2.0G 2% /tmp /dev/mapper/rootvg-optlv 2.0G 140M 1.9G 7% /opt /dev/mapper/rootvg-varlv 8.0G 184M 7.9G 3% /var /dev/sdb1 16G 45M 15G 1% /mnt /dev/sdc1 42M 1.5K 42M 1% /mnt/azure_bek_disk tmpfs 783M 0 783M 0% /run/user/1000
AzureAD認証で異なるテナント間のBlobコピー
ドキュメントには特段記載がないと思っていたところ、現在のところサポートされないシナリオでした。
AzCopy v10 を使用して Azure ストレージ アカウント間で BLOB をコピーする | Microsoft Learn
移行元アカウントと移行先アカウントは、同じ Azure AD テナントに属している必要があります。
一応、行うとどんなエラーとなるかメモ。
事前準備
-テナントAでストレージ アカウントを作成 -テナントBでストレージアカウントを作成 -ダミーファイル (1MB) を複数作成し、テナントAのストレージアカウントにアップロード
for /l %n in (1,1,3000) do fsutil file createnew %n 1048576
-操作アカウントに対して、以下のRBACを付与 - テナントAストレージアカウント; ストレージBLOBデータ閲覧者 - テナントBストレージアカウント; ストレージBLOB共同作成者
コピーの実行
PS > azcopy login --tenant-id "aaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code XXXXXXXXX to authenticate. INFO: Login succeeded. PS > azcopy login --tenant-id "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code XXXXXXXXX to authenticate. INFO: Login succeeded.
azcopy copyを実行すると、どうやらデータコピー元に対して参照操作が認証エラー
PS > azcopy copy "https://<src>.blob.core.windows.net/src/testdata" "https://<dest>.blob.core.windows.net/dest" --recursive INFO: Scanning... INFO: Authenticating to destination using Azure AD INFO: Authenticating to source using Azure AD INFO: Any empty folders will not be processed, because source and/or destination doesn't have full folder support failed to perform copy command due to error: cannot start job due to error: cannot list files due to reason -> github.com/Azure/azure-storage-blob-go/azblob.newStorageError, /home/vsts/go/pkg/mod/github.com/!azure/azure-storage-blob-go@v0.15.0/azblob/zc_storage_error.go:42 ===== RESPONSE ERROR (ServiceCode=InvalidAuthenticationInfo) ===== Description=Server failed to authenticate the request. Please refer to the information in the www-authenticate header. RequestId:39925b77-701e-0041-5a55-06a0e8000000 Time:2022-12-02T13:56:13.9916736Z, Details: AuthenticationErrorDetail: Issuer validation failed. Issuer did not match. Code: InvalidAuthenticationInfo GET https://<src>.blob.core.windows.net/src?comp=list&delimiter=%2F&include=metadata&prefix=testdata%2F&restype=container&timeout=901 Authorization: REDACTED User-Agent: [AzCopy/10.16.2 Azure-Storage/0.15 (go1.17.9; Windows_NT)] X-Ms-Client-Request-Id: [833ede1e-8e87-4dbc-6777-f49b2fdb66e6] X-Ms-Version: [2020-10-02] -------------------------------------------------------------------------------- RESPONSE Status: 401 Server failed to authenticate the request. Please refer to the information in the www-authenticate header. Content-Length: [402] Content-Type: [application/xml] Date: [Fri, 02 Dec 2022 13:56:13 GMT] Server: [Microsoft-HTTPAPI/2.0] Www-Authenticate: [Bearer authorization_uri=https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47/oauth2/authorize resource_id=https://storage.azure.com] X-Ms-Error-Code: [InvalidAuthenticationInfo] X-Ms-Request-Id: [39925b77-701e-0041-5a55-06a0e8000000]
下記の開発元からのコメントにあるように、現時点では非サポートの状況
回避策
コピー元、コピー先のストレージアカウントのどちらかのみに対しAzure AD認証を使うのはOKなので、もう一方は例えばSAS使ってコピーができます。
テナントA (Azure AD) -> テナントB (SAS)
コピー先のコンテナーに対して、SASトークンを発行 (アクセス許可 : 作成)
PS > azcopy login --tenant-id "aaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code XXXXXXXXX to authenticate. INFO: Login succeeded. PS > azcopy copy "https://<src>.blob.core.windows.net/src/testdata" "https://<dest>.blob.core.windows.net/dest?sp=c&st=2022-12-03T07:24:55Z&se=2022-12-03T15:24:55Z&spr=https&sv=2021-06-08&sr=c&sig=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" --recursive INFO: Scanning... INFO: Authenticating to source using Azure AD INFO: Failed to create one or more destination container(s). Your transfers may still succeed if the container already exists. INFO: Any empty folders will not be processed, because source and/or destination doesn't have full folder support Job ef855a5f-2cd9-174f-6bc2-d0f8aab4798f has started Log file is located at: C:\Users\<user>\.azcopy\ef855a5f-2cd9-174f-6bc2-d0f8aab4798f.log INFO: Could not read destination length. If the destination is write-only, use --check-length=false on the command line. 100.0 %, 3000 Done, 0 Failed, 0 Pending, 0 Skipped, 3000 Total, 2-sec Throughput (Mb/s): 2707.3708 Job ef855a5f-2cd9-174f-6bc2-d0f8aab4798f summary Elapsed Time (Minutes): 0.1001 Number of File Transfers: 3000 Number of Folder Property Transfers: 0 Total Number of Transfers: 3000 Number of Transfers Completed: 3000 Number of Transfers Failed: 0 Number of Transfers Skipped: 0 TotalBytesTransferred: 3145728000 Final Job Status: Completed
テナントA (SAS) -> テナントB (Azure AD)
コピー元のコンテナーに対して、SASトークンを発行 (アクセス許可 : 読み取り/リスト)
PS > azcopy login --tenant-id "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code XXXXXXXXX to authenticate. INFO: Login succeeded. PS > azcopy copy "https://<src>.blob.core.windows.net/src?sp=rl&st=2022-12-03T07:31:27Z&se=2022-12-03T15:31:27Z&spr=https&sv=2021-06-08&sr=c&sig=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" "https://<dest>.blob.core.windows.net/dest" --recursive INFO: Scanning... INFO: Authenticating to destination using Azure AD INFO: Authentication: If the source and destination accounts are in the same AAD tenant & the user/spn/msi has appropriate permissions on both, the source SAS token is not required and OAuth can be used round-trip. INFO: Any empty folders will not be processed, because source and/or destination doesn't have full folder support Job 37be841c-fb7a-f048-603d-33b3c1d44aa2 has started Log file is located at: C:\Users\<user>\.azcopy\37be841c-fb7a-f048-603d-33b3c1d44aa2.log INFO: Transfers could fail because AzCopy could not verify if the destination supports tiers. 100.0 %, 3000 Done, 0 Failed, 0 Pending, 0 Skipped, 3000 Total, 2-sec Throughput (Mb/s): 4798.4101 Job 37be841c-fb7a-f048-603d-33b3c1d44aa2 summary Elapsed Time (Minutes): 0.1005 Number of File Transfers: 3000 Number of Folder Property Transfers: 0 Total Number of Transfers: 3000 Number of Transfers Completed: 3000 Number of Transfers Failed: 0 Number of Transfers Skipped: 0 TotalBytesTransferred: 3145728000 Final Job Status: Completed
プライベートコンテナレジストリ(Harbor)を構築
Azure CLIベースでHarborの構築メモ。 流れとしては以下となります。
1. コンテナレジストをデプロイするVNetを作成
リソースグループを作成
az group create --name labprivcr --location japaneast
次に仮想ネットワークとサブネットを作成
$ az network vnet create --resource-group labprivcr --name vnetforprivcr --address-prefixes 10.0.0.0/16 --subnet-name subnet1 --subnet-prefixes 10.0.0.0/24
2.コンテナレジストリを構築
要件を見ると、4 CPU / メモリ 8GB / ディスク 160 GB とあるので、B4ms サイズ (4 vCPU / 16 Gib メモリ) を選択 Harbor docs | Harbor Installation Prerequisites
Harbor 用に仮想マシンを作成 ローカルでのみ利用する想定なので、パブリックIPアドレスは付与していません。
$ az vm create --resource-group labprivcr --name privcr --image UbuntuLTS --vnet-name vnetforprivcr --subnet subnet1 --admin-username azureuser --ssh-key-values ~/.ssh/id_rsa.pub --public-ip-address "" --size Standard_B4ms
プライベートDNSゾーンを設定し、仮想ネットワークにリンク。
az network private-dns link vnet create
の際に、--registration-enabled false
としているのは、後々 VNetピアリングしたとき、そこにデプロイしたAKSノードも登録されてしまうため、必要なものだけ登録するよう、false
を設定しています。
$ az network private-dns zone create --resource-group labprivcr --name labprivcr.com $ az network private-dns link vnet create --resource-group labprivcr --name labprivcrlink --zone-name labprivcr.com --virtual-network vnetforprivcr --registration-enabled false $ az network private-dns record-set a add-record --resoruce-group labprivcr --zone-name labprivcr.com --record-set-name privcr --ipv4-address 10.0.0.4
踏み台サーバをデプロイ こちらはパブリックIPアドレスを付与します。
$ az vm create --resource-group labprivcr --name jumpbox --image UbuntuLTS --vnet-name vnetforprivcr --subnet subnet1 --admin-username azureuser --ssh-key-values ~/.ssh/id_rsa.pub
踏み台サーバがデプロイできたら、踏み台サーバ→プライベートコンテナレジストリ用VMにSSH接続します。
$ scp -p ~/.ssh/id_rsa azureuser@xxx.xxx.xxx.xxx:/home/azureuser/.ssh/ $ ssh azureuser@xxx.xxx.xxx.xxx $ ssh azureuser@privcr
Dockerをインストール
参考; Install Docker Engine on Ubuntu | Docker Documentation
$ sudo apt-get update $ sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - $ sudo apt-key fingerprint 0EBFCD88 $ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" $ sudo apt-get update $ sudo apt-get install docker-ce docker-ce-cli containerd.io $ sudo docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 0e03bdcc26d7: Pull complete Digest: sha256:1a523af650137b8accdaed439c17d684df61ee4d74feac151b5b337bd29e7eec Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/
一般ユーザでもdockerコマンドが実行できるよう、dockerグループに追加
$ sudo usermod -aG docker `whoami` azureuser@privcr:~$ exit azureuser@privcr:~$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 218ed82c7541 hello-world "/hello" 55 seconds ago Exited (0) 51 seconds ago brave_agnesi
Docker-composeをインストール
参考; Install Docker Compose | Docker Documentation
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose $ sudo chmod +x /usr/local/bin/docker-compose $ docker-compose --version docker-compose version 1.27.4, build 40524192
HarborをHTTPSアクセス可能なように自己証明書を作成
これもほとんど公式ドキュメント通り
参考; Harbor docs | Configure HTTPS Access to Harbor
CA証明書の秘密鍵 ca.key
を作成
$ mkdir cert && cd cert $ openssl genrsa -out ca.key 4096
CA証明書 ca.crt
を作成
$ openssl req -x509 -new -nodes -sha512 -days 3650 -subj "/C=JP/ST=Tokyo/L=Tokyo/O=lab/OU=lab/CN=privcr.labprivcr.com" -key ca.key -out ca.crt
このとき、Can't load /home/azureuser/.rnd into RNG
とエラーになったので、以下の情報に沿って、/etc/ssl/openssl.cnf
の RANDFILE
行をコメントアウト
参考; Can't load ./.rnd into RNG · Issue #7754 · openssl/openssl · GitHub
サーバ証明書の秘密鍵 privcr.labprivcr.com.key
を作成
$ openssl genrsa -out privcr.labprivcr.com.key 4096
証明書署名要求 privcr.labprivcr.com.csr
を作成
$ openssl req -sha512 -new -subj "/C=JP/ST=Tokyo/L=Tokyo/O=lab/OU=lab/CN=privcr.labprivcr.com" -key privcr.labprivcr.com.key -out privcr.labprivcr.com.csr
x509 v3 拡張属性向けの設定ファイルを生成
$ cat > v3.ext <<-EOF authorityKeyIdentifier=keyid,issuer basicConstraints=CA:FALSE keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names [alt_names] DNS.1=privcr.labprivcr.com DNS.2=privcr IP.1=10.0.0.4 EOF
サーバ証明書 privcr.labprivcr.com.crt
を作成
$ openssl x509 -req -sha512 -days 3650 -extfile v3.ext -CA ca.crt -CAkey ca.key -CAcreateserial -in privcr.labprivcr.com.csr -out privcr.labprivcr.com.crt
$ sudo mkdir -p /data/cert $ sudo cp privcr.labprivcr.com.crt /data/cert/ $ sudo cp privcr.labprivcr.com.key /data/cert/
Docker向けに privcr.labprivcr.com.crt を privcr.labprivcr.com.cert に変換し、配置
$ openssl x509 -inform PEM -in privcr.labprivcr.com.crt -out privcr.labprivcr.com.cert $ sudo mkdir -p /etc/docker/certs.d/privcr.labprivcr.com $ sudo cp privcr.labprivcr.com.cert /etc/docker/certs.d/privcr.labprivcr.com/ $ sudo cp privcr.labprivcr.com.key /etc/docker/certs.d/privcr.labprivcr.com/ $ sudo cp ca.crt /etc/docker/certs.d/privcr.labprivcr.com/
更新を反映させるため、dockerを再起動
$ sudo systemctl restart docker
Harborをインストール
$ wget https://github.com/goharbor/harbor/releases/download/v2.1.2/harbor-online-installer-v2.1.2.tgz $ tar xvf harbor-online-installer-v2.1.2.tgz $ cd harbor $ cp harbor.yml.tmpl harbor.yml $ vi harbor.yml diff harbor.yml harbor.yml.tmpl 5c5 < hostname: privcr.labprivcr.com --- > hostname: reg.mydomain.com 17,18c17,18 < certificate: /etc/docker/certs.d/privcr.labprivcr.com/privcr.labprivcr.com.cert < private_key: /etc/docker/certs.d/privcr.labprivcr.com/privcr.labprivcr.com.key --- > certificate: /your/certificate/path > private_key: /your/private/key/path
インストール
$ sudo ./install.sh ... Creating harbor-log ... done Creating registryctl ... done Creating harbor-portal ... done Creating registry ... done Creating redis ... done Creating harbor-db ... done Creating harbor-core ... done Creating harbor-jobservice ... done Creating nginx ... done ✔ ----Harbor has been installed and started successfully.----
ログイン可能か確認。デフォルトのパスワードは、harbor.yml
に記載のある通り、
Harbor12345
$ docker login privcr.labprivcr.com Username: admin Password: WARNING! Your password will be stored unencrypted in /home/yuri/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded
3.踏み台サーバにGUI環境を構築しHarborにアクセス
Web UIがあるので、踏み台サーバにGUI環境を構築し確認
UbuntuはAzureのドキュメント通り
参考; Azure の Linux VM にリモート デスクトップを使用する - Azure Virtual Machines | Microsoft Docs
$ sudo apt-get update $ sudo apt-get install xfce4 $ sudo apt-get install xrdp $ sudo systemctl enable xrdp $ echo xfce4-session >~/.xsession $ sudo systemctl restart xrdp
ログインユーザのパスワードを設定
sudo passwd azureuser Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully
Webブラウザが入っていないので、Firefoxをインストール
$ sudo apt-get install firefox
3389/TCPを踏み台サーバのNSGなどで許可 その後、RDP接続にてGUI環境が利用できます。
先に作成したCA証明書を踏み台サーバにコピーし、Firefoxにインポートします。
- Settings > Privacy & Security > View Certificates...
- Import...
あとはFirefoxからhttps://privcr.labprivcr.comにアクセス
4.DockerイメージをHarborにプッシュ
次にHarborにDockerイメージをプッシュしてみます。
踏み台サーバに、プライベートコンテナレジストリと同様の手順でDockerをインストール
CA証明書をインストール
$ scp yuri@privcr:/home/yuri/cert/ca.crt . $ sudo cp ca.crt /usr/local/share/ca-certificates/ $ sudo update-ca-certificates
Harborにログインし、Dockerイメージをプッシュ libraryというプロジェクトはプリセットのものらしいです。
$ docker login privcr.labprivcr.com Username: admin Password: WARNING! Your password will be stored unencrypted in /home/azureuser/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded $ docker tag hello-world:latest privcr.labprivcr.com/library/hello-world:v1 $ docker push privcr.labprivcr.com/library/hello-world:v1 The push refers to repository [privcr.labprivcr.com/library/hello-world] 9c27e219663c: Pushed v1: digest: sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 size: 525
Web UIからも確認できました。
AKSでネットワークパケットキャプチャを取得する
どこそこへつながらないや、つながるけどたまに切れるといった場面でネットワークパケットキャプチャを取得することがあるかと思います。 AKSの場合にどうやって取得するのかまとめてみました。
AKSノードにて取得
対象AKSノードにSSH接続し取得する方法で、一番簡単で取得可能な方法になります。
反面、解析する際には !(ip.addr == 168.63.129.16)
等、フィルタリングして目的の通信を見る必要があります。
参考; IP アドレス 168.63.129.16 とは | Microsoft Docs
AKSノードに到達可能な仮想ネットワークに踏み台サーバを用意するか、以下のヘルパーPod経由で対象AKSノードにSSH接続
Azure Kubernetes Service (AKS) クラスター ノードへの SSH 接続 - Azure Kubernetes Service | Microsoft Docs
2.ネットワークパケットキャプチャを取得する
sudo tcpdump -i any -s 0 -vvv -w `hostname`.pcap ... 対象のアクセスや操作を実行後、[Ctrl]+[C] により完了
3.対象ノードからネットワークパケットキャプチャを引き上げる
AKSノードからヘルパーPod/踏み台サーバへ scp コマンドによりコピーし、次いで、ローカル環境にコピー ヘルパーPodからローカル環境にコピーするには以下のように実施
kubectl cp $(kubectl get pod -l run=aks-ssh -o jsonpath='{.items[0].metadata.name}'):/(パケットキャプチャ結果).pcap (パケットキャプチャ結果).pcap
Podから取得
フィルタリングが楽であるためにPodからネットワークパケットキャプチャを取得できることが望ましいですが、 distrolessイメージの利用など、なるべくtcpdumpコマンドなど省いて作られたイメージを使うことが推奨事項になっています。
本命は、Ephemeral Container (kubectl debug コマンド) により対象のPodを変更させず、ネットワーク名前空間を共有する一時的なPodから取得する方法です。
Debug Running Pods | Kubernetes
上記はAlphaステージの機能のため、AKSなどのマネージドKubernetesでは対応していない状況です (GKEのアルファクラスターなら可能?)。 それに代わるものとして、ksniffというツールが現時点ではよさそうな印象があります。
# 1.5.0 では問題があり (https://github.com/eldadru/ksniff/issues/82)、1.4.2を利用します $ wget https://github.com/eldadru/ksniff/releases/download/v1.4.2/ksniff.zip $ unzip ksniff.zip $ sudo make install $ kubectl sniff -p (Pod名) -n (名前空間名) -o (出力先ファイル名).pcap ... 対象のアクセスや操作を実行後、[Ctrl]+[C] により完了 ````
AKSノードにnode-shellでログインする
AKSにてノード (仮想マシンスケールセットインスタンス) に接続するとき、Podをデプロイしてそれを経由し、ノードにアクセスが必要。 しかし、ちょっと面倒なので、kubectl-node-shellを使ってみる。
krewと呼ばれるkubectlのプラグイン管理ツールによりインストールできる。
❯ kubectl krew index add kvaps https://github.com/kvaps/krew-index ❯ kubectl krew install kvaps/node-shell
使ってみると、実行中のコンテナも見れたりする。
❯ kubectl get nodes NAME STATUS ROLES AGE VERSION aks-nodepool1-31996622-vmss000000 Ready agent 9h v1.18.10 aks-nodepool1-31996622-vmss000001 Ready agent 9h v1.18.10 akswinp000000 Ready agent 9h v1.18.10 ❯ kubectl node-shell aks-nodepool1-31996622-vmss000000 spawning "nsenter-bsxuel" on "aks-nodepool1-31996622-vmss000000" If you don't see a command prompt, try pressing enter. root@aks-nodepool1-31996622-vmss000000:/# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 879f57bf3305 alpine "nsenter --target 1 …" 16 seconds ago Up 16 seconds k8s_nsenter_nsenter-bsxuel_default_74057696-8b44-49a1-bc5f-31e2666efc12_0 ...(省略)...
動作としては、alpineイメージのコンテナから、nsenterコマンドにてpidが1を指定してノードに入っている。 そのため、Windows ノードでは残念ながら動作しなかった。
❯ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nsenter-21fo6d 0/1 ContainerCreating 0 138m 10.240.0.66 akswinp000000 <none> <none>
Windows コンテナ
Windows コンテナとは
Windows Server 2016よりサポートされたWindowsコンテナ、Linuxコンテナはまずまず不自由なく使うぐらいは触っているけど、 いまいち利用用途など見いだせず、敬遠し続けていた。
ということで、入門してみます。
2つの分離モード
Linuxと異なる点として、「プロセス分離」、「Hyper-V分離」の2つがある点が挙げられます。 前者は、Linuxコンテナと同様に、ホストのカーネルは共有する形態で、後者はホスト上に軽量の仮想マシンを挟み、その上でコンテナを動かす形態。
後者のメリットは、動作するWindowsコンテナのバージョンがホストOSのバージョンに制約されないことと、 Linuxコンテナ(いわゆる Linux Container on Windows, LCOW)もこれにより実現。
デフォルトは、プロセス分離
PS> docker info ... Default Isolation: process ...
環境構築
- Azure仮想マシンとしてWindows (Windows Server 2019 Datacenter)をデプロイ
- Hyper-V機能を有効化
- Docker EEをインストール
IIS をデプロイして確認してみる
使う Dockerfileはこちら。
gist41fe3ca2d129c29074aa68d939bb94e6
ポイントは、
* エスケープ文字がデフォルトではバッククォートであるため、 escape
で変更 (Windowsの場合、バッククォートでディレクトリを分けるため)
* LogMonitorにより、ETW形式のログを標準出力に出すように設定
* ServiceMonitorを用いて、IISをサービスとして管理
PS>docker build -t iis:v1 https://gist.githubusercontent.com/yuriwoof/41fe3ca2d129c29074aa68d939bb94e6/raw/3db06040b7acc9ad940a3d60c9ea3b4d062befb0/Dockerfile.iis PS>docker run -d -p 8000:80 --name iis iis:v1
PS> docker logs -f iis <Source>EtwEvent</Source><Time>2020-11-03T13:31:33.000Z</Time><Provider idGuid="{7E8AD27F-B271-4EA2-A783-A47BDE29143B}"/><DecodingSource>DecodingSourceXMLFile</DecodingSource><Execution ProcessID="8480" ThreadID="9152" /><Level>Information</Level><Keyword>0x8000000000000000</Keyword><EventID Qualifiers="6200">6200</EventID><EventData><EnabledFieldsFlags>2478079</EnabledFieldsFlags><date>2020-11-03</date><time>13:31:30</time><c-ip>172.16.3.4</c-ip><cs-username>-</cs-username><s-sitename>W3SVC1</s-sitename><s-computername>34c7189aaf3d</s-computername><s-ip>172.18.242.44</s-ip><cs-method>GET</cs-method><cs-uri-stem>/iisstart.png</cs-uri-stem><cs-uri-query>-</cs-uri-query><sc-status>304</sc-status><sc-win32-status>0</sc-win32-status><sc-bytes>143</sc-bytes><cs-bytes>530</cs-bytes><time-taken>2</time-taken><s-port>80</s-port><csUser-Agent>Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/86.0.4240.183+Safari/537.36</csUser-Agent><csCookie>-</csCookie><csReferer>http://localhost:8000/</csReferer><cs-version>-</cs-version><cs-host>-</cs-host><sc-substatus>0</sc-substatus><CustomFields></CustomFields></EventData>
クラスターオートスケール機能
大分昔に更新して以来すっかり更新を放置していたので、久しぶりに更新してみようと。
前回からすると、お仕事も一新 Azure を触る機会が多くなりました。 いろいろと検証するのですが、書き溜めたメモがなかなか放流できずじまいに。
今回は、Azure Kubernetes Service (AKS) でたまに聞かれることがあるクラスターオートスケール機能について書いてみます。
Azure Kubernetes Service (AKS) でのアプリケーションの需要を満たすようにクラスターを自動的にスケーリング
Kubernetes のオートスケール機能
オートスケールの対象は、PodとNode です。
Pod は、負荷に応じて、Pod 数を増減させる水平オートスケールと、Pod 数ではなく割り当てる CPU / メモリリソースを調整する垂直オートスケール機能があります。
Node の方は、クラスターオートスケール という機能で、負荷状況ではなく、
Pod が割り当てられない (Pending) になった時点で Node を追加する仕組みになります。
現時点で、 AKS でサポートしているのは、水平オートスケール機能とクラスターオートスケール機能になります。
検証
それでは検証してみます。 まずは AKS クラスターを構築します。
$ az group create --name labca --location japaneast $ az aks create \ --resource-group labca \ --name labca \ --node-count 1 \ --node-vm-size Standard_DS2_v2 \ --enable-vmss \ --enable-cluster-autoscaler \ --min-count 1 \ --max-count 3
Standard_DS2_v2 なので、1 ノード当たり 2 vCPU (2000m) 持つことになります (実際、割り当て可能なのは、1900m)。
$ az aks get-credentials -g labca -n labca $ kubectl get nodes NAME STATUS ROLES AGE VERSION aks-nodepool1-24609861-vmss000000 Ready agent 12m v1.15.10
それでは、以下のようなシナリオで Node が追加されることを確認してみます。
- 水平オートスケール (HorizontalpodAutoscaler) により、CPU 負荷が 50 % 以上を超えた場合、Pod を最大 5 つまでスケールアウトさせる
- 対象のPodでは、絶えず負荷がかかるようにしておく
まずは水平オートスケールリソースを作成
$ cat << EOF | kubectl apply -f - apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata: name: stress-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: stress minReplicas: 1 maxReplicas: 5 targetCPUUtilizationPercentage: 50 EOF
次いでオートスケール対象のPodを作成
$ cat << EOF | kubectl apply -f - apiVersion: apps/v1 kind: Deployment metadata: name: stress namespace: default spec: replicas: 1 selector: matchLabels: app: stress template: metadata: labels: app: stress spec: containers: - name: stress-test image: busybox command: ["dd", "if=/dev/zero", "of=/dev/null"] resources: limits: cpu: 500m requests: cpu: 500m EOF
Pod の増加を見てみます。 他の管理系のPodがあるため、2つ (cpu : 1000m)分のみしかRunningになりませんでした。
kubectl get pods NAME READY STATUS RESTARTS AGE stress-864dc999dd-cpbk2 1/1 Running 0 65s stress-864dc999dd-khfxp 1/1 Running 0 2m stress-864dc999dd-lnggt 0/1 Pending 0 5s stress-864dc999dd-ngbq7 0/1 Pending 0 5s
次いでクラスターオートスケールの状態を確認すると、Eventsにスケールアップのイベントが発生していることが分かります(vmss サイズを2に変更した旨)。
$ kubectl describe configmap -n kube-system cluster-autoscaler-status ...(省略)... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScaledUpGroup 80s cluster-autoscaler Scale-up: setting group aks-nodepool1-24609861-vmss size to 2 Normal ScaledUpGroup 80s cluster-autoscaler Scale-up: group aks-nodepool1-24609861-vmss size set to 2
しばらく待つと、Nodeが追加されました。
$ kubectl get nodes NAME STATUS ROLES AGE VERSION aks-nodepool1-24609861-vmss000000 Ready agent 25m v1.15.10 aks-nodepool1-24609861-vmss000001 Ready agent 35s v1.15.10
それに伴い、PendingになっていたPodもデプロイされ、5つすべてRunningになります。
$ kubectl get pods NAME READY STATUS RESTARTS AGE stress-864dc999dd-cpbk2 1/1 Running 0 15m stress-864dc999dd-ffrtq 1/1 Running 0 10m stress-864dc999dd-khfxp 1/1 Running 0 16m stress-864dc999dd-lnggt 1/1 Running 0 14m stress-864dc999dd-ngbq7 1/1 Running 0 14m
以上にようにアプリケーションの負荷に伴い、インフラ側でも柔軟に対応させることが可能となります。
Nodeの増減に関してより細かい設定を行うことも可能です。