2023年1月28日土曜日

【PowerCLI】仮想マシンハードウェアをバージョンアップする方法

ESXiをバージョンアップした際などに、仮想マシンのサマリ画面にて「この仮想マシンに設定されたゲストは、現在実行中のゲストと一致しません」といった警告メッセージが表示される場合がある。

これは、バージョンアップ前のESXiでは対応していなかったOS種別が、新しいESXiの仮想マシンハードウェアで対応したことの影響となる。

特に仮想マシンの動作に影響を及ぼすものではないが、警告メッセージを消したい場合は、ハードウェアバージョンアップを行ったのち、仮想マシンのゲストOS設定を修正する必要がある。ただし、仮想マシンのハードウェアバージョンアップはVMware Host Clientでは行うことはできない。

そこで本記事では、PowerCLIを用いて仮想マシンハードウェアをバージョンアップをする方法を記載する。

環境

本環境を実施した環境は以下の通り。vCenter Serverは構築していないため、ESXiに対してPowerCLIからコマンド実行を行う。

  • ESXi : 7.0 Update 3 (20328353)
  • PowerCLI : 12.7.0 build 20091289
  • 作業対象仮想マシン名 : vyos
    • 仮想マシンハードウェア(前) : vmx-14
    • 仮想マシンハードウェア(後) : vmx-19

仮想マシンハードウェアのバージョンアップ手順

1. 仮想マシンを停止

本作業の前提として仮想マシンの停止が必要となるため、あらかじめ作業対象の仮想マシンを停止しておく。

2. バージョンアップ前確認

バージョンアップ前に仮想マシンハードウェアのバージョン確認を行う。HardwareVersionが仮想マシンハードウェアを表しており、バージョンアップ前はvmx-14であることがわかる。これはESXi 6.7が対応しているバージョンとなる。

PS> Get-VM vyos| fl *

Name                    : vyos
PowerState              : PoweredOff

~(中略)~

Version                 : v14
HardwareVersion         : vmx-14 ★
PersistentId            : 528c62f8-48d4-4ccc-0a7d-a05c02f07afa
GuestId                 : debian10_64Guest

~(以下略)~

2. バージョンアップ前スナップショット取得

バージョンアップ前に念のため仮想マシンのスナップショットを取得しておく。

PS> Get-VM vyos| New-Snapshot -Name "Before hardware version upgrade"

Name                 Description                    PowerState
----                 -----------                    ----------
Before hardware v...                                PoweredOff

3. 仮想マシンハードウェアをバージョンアップ

バージョンアップは以下コマンドで実行する。今回はESXi 7.0 Update 2以降で対応しているvmx-19にバージョンアップを行った。コマンドを実行すれば処理はすぐに完了する。

PS> (Get-VM vyos).ExtensionData.UpgradeVM('vmx-19')

なお、以前のPowerCLIではSet-VMコマンドレットでバージョンアップできたようだが、PowerCLI 12.7では以下の通り実行に失敗するので注意。

PS> Get-VM vyos| Set-VM -Version "v19" -Confirm:$false
Set-VM : パラメーター 'Version' をバインドできません。値 "v19" を型 "VMware.VimAutomation.ViCore.Types.V1.VM.VMVersion"
 に変換できません。エラー: "識別子名 v19 は有効な列挙子名に一致しません。次のいずれかの列挙子名を指定して再試行してくだ
さい:
Unknown, v4, v7, v8, v9, v10, v11, v12, v13, v14"
発生場所 行:1 文字:36
+ Get-VM vyos| Set-VM -Version "v19" -Confirm:$false
+                                    ~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Set-VM]、ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,VMware.VimAutomation.ViCore.Cmdlets.Commands.SetVM

4. バージョンアップ後確認

バージョンアップ後の仮想マシンの状態確認を行う。HardwareVersionvmx-19になっていれば問題ない。

PS> Get-VM vyos| fl *


警告: The 'Version' property of VirtualMachine type is deprecated. Use the 'HardwareVersion' property instead.
Name                    : vyos
PowerState              : PoweredOff

~(中略)~

Version                 : Unknown
HardwareVersion         : vmx-19 ★
PersistentId            : 528c62f8-48d4-4ccc-0a7d-a05c02f07afa
GuestId                 : debian10_64Guest

~(以下略)~

5. ゲストOS設定変更&仮想マシン起動

VMware Host Clientにログインし、[対象の仮想マシン]→[設定の編集]→[仮想マシン オプション]→[一般オプション]→[ゲストOSのバージョン]から、警告メッセージに表示されていたOSを選択する。なお、仮想マシンハードウェアのバージョンをバージョンアップしていない場合は、そもそも選択肢に新しいOSは表示されないため注意しよう。

その後、仮想マシンを起動することで、警告メッセージが消えるはずだ。

6. バージョンアップ後スナップショット削除

その後の仮想マシンが問題なく起動したようであれば、作業前のバックアップを削除する。

PS> Get-VM vyos| Get-Snapshot -Name "Before hardware version upgrade" | Remove-Snapshot -Confirm:$false

以上で、PowerCLIを用いて仮想マシンハードウェアをバージョンアップをする方法の説明は終了となる。

参考

2023年1月21日土曜日

【PowerShell】Windowsのディスクのオンライン・オフラインとドライブレターを設定する

Windowsでは通常、昔から変わらない「ディスクの管理」画面を開いてディスクのオンライン・オフラインや、ドライブレターの変更作業をすることが多い。

あまりシチュエーションとしては多くないかもしれないが、定期的にディスクをオンライン・オフラインにしたりドライブレターの変更をする作業があるかもしれない。そのような場合は、PowerShellを使えば同様の作業がCLIベースで実施でき、あらかじめスクリプトなどを作っておけば自動化も可能となる。

本記事では、PowerShellを使ってWindowsのディスクのオンライン・オフラインとドライブレター変更の手順を記載する。

環境

Windows Server 2019を用いて動作確認を行った。

ディスクはCドライブ以外に2つ用意する。ディスク1をオンライン、ディスク2をオフラインにしておき、PowerShellを用いて以下の通りディスクの入れ替えを行う。

作業前

ディスクNo ドライブレター 容量 [GB] 状態
0 C 40 オンライン
1 U 30 オンライン
2 なし 32 オフライン

作業前

ディスクNo ドライブレター 容量 [GB] 状態
0 C 40 オンライン
1 なし 30 オフライン
2 U 32 オンライン

ディスクのマウント手順

1. ディスクの状態を確認

作業対象のディスクを確認する。ディスク情報を確認するコマンドレットは、以下3つが存在する。

コマンドレット 説明
Get-Disk 物理ディスクの一覧を表示する。オフラインのディスクも表示される。
Get-Volume 初期化及びフォーマット済みのディスクの一覧を表示する。オフラインのディスク上のボリュームは表示されない。
Get-Partition 各ディスクのパーティション一覧を表示する。オフラインのディスク上のパーティションは表示されない。

実行結果を以下に示す。

Get-Disk

PS C:\> Get-Disk

Number Friendly Name Serial Number                    HealthStatus         OperationalStatus      Total Size Partition
                                                                                                             Style
------ ------------- -------------                    ------------         -----------------      ---------- ----------
0      VMware Vir... 6000c298f4905127fbf4b8af93289b7c Healthy              Online                      40 GB GPT
1      VMware Vir... 6000c29155e1a0ea6d59319bfb0965df Healthy              Online                      30 GB GPT
2      VMware Vir... 6000c298d8b95c7aa7fa9c84622b5faa Healthy              Offline                     32 GB GPT

Get-Volume

PS C:\> Get-Volume

DriveLetter FriendlyName FileSystemType DriveType HealthStatus OperationalStatus SizeRemaining      Size
----------- ------------ -------------- --------- ------------ ----------------- -------------      ----
            回復         NTFS           Fixed     Healthy      OK                     57.05 MB    499 MB
D           VMware Tools Unknown        CD-ROM    Healthy      OK                          0 B 140.61 MB
C                        NTFS           Fixed     Healthy      OK                     29.84 GB   39.4 GB
U           ボリューム   NTFS           Fixed     Healthy      OK                     20.32 GB  29.98 GB
                         FAT32          Fixed     Healthy      OK                     69.12 MB     95 MB

Get-Partition

PS C:\> Get-Partition

   DiskPath: \\?\scsi#disk&ven_vmware&prod_virtual_disk#000000#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}

PartitionNumber  DriveLetter Offset                                        Size Type
---------------  ----------- ------                                        ---- ----
1                            1048576                                     499 MB Recovery
2                            524288000                                    99 MB System
3                            628097024                                    16 MB Reserved
4                C           644874240                                  39.4 GB Basic


   DiskPath: \\?\scsi#disk&ven_vmware&prod_virtual_disk#000100#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}

PartitionNumber  DriveLetter Offset                                        Size Type
---------------  ----------- ------                                        ---- ----
1                            17408                                     15.98 MB Reserved
2                U           16777216                                  29.98 GB Basic


   DiskPath: \\?\scsi#disk&ven_vmware&prod_virtual_disk#000200#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}

PartitionNumber  DriveLetter Offset                                        Size Type
---------------  ----------- ------                                        ---- ----
1                            17408                                     15.98 MB Reserved
2                            16777216                                  31.98 GB Basic

2. ディスク設定変更

確認結果より、今回はディスクNo1とディスクNo2をPowerShellにて入れ替える。

ディスクのオンライン・オフラインはSet-Diskコマンドレットで共通して操作可能だが、ドライブレターの削除(Remove-PartitionAccessPath)と追加(Set-Partition)はコマンドレットが異なる点に注意しよう。

# 取り外し対象ディスクNo
$old_disk_number=1
$old_driveletter=(Get-Disk -Number ${new_disk_number} | Get-Partition -Number 2).DriveLetter
# 取付対象ディスクNo
$new_disk_number=2
$new_driveletter="U"

# ドライブレターの削除
Get-Disk -Number ${old_disk_number} | Get-Partition -Number 2 | Remove-PartitionAccessPath -AccessPath "${old_driveletter}:"
# ディスクのオフライン
Get-Disk -Number ${old_disk_number} | Set-Disk -IsOffline $true

# ディスクのオンライン
Get-Disk -Number ${new_disk_number} | Set-Disk -IsOffline $false
# ドライブレターの付与
Get-Disk -Number ${new_disk_number} | Get-Partition -Number 2 | Set-Partition -NewDriveLetter ${new_driveletter}

ディスクの状態を戻す場合は、ディスクNoの変数を入れ替えればよい (★箇所)。

# 取り外し対象ディスクNo
$old_disk_number=2 #←★2に変更
$old_driveletter=(Get-Disk -Number ${new_disk_number} | Get-Partition -Number 2).DriveLetter
# 取付対象ディスクNo
$new_disk_number=1 #←★1に変更
$new_driveletter="U"

# ドライブレターの削除
Get-Disk -Number ${old_disk_number} | Get-Partition -Number 2 | Remove-PartitionAccessPath -AccessPath "${old_driveletter}:"
# ディスクのオフライン
Get-Disk -Number ${old_disk_number} | Set-Disk -IsOffline $true

# ディスクのオンライン
Get-Disk -Number ${new_disk_number} | Set-Disk -IsOffline $false
# ドライブレターの付与
Get-Disk -Number ${new_disk_number} | Get-Partition -Number 2 | Set-Partition -NewDriveLetter ${new_driveletter}

以上で、PowerShellを使ってィスクのオンライン・オフラインとドライブレター変更の手順は完了となる。

参考

2023年1月14日土曜日

AnsibleでVyOSを操作する

自宅ではAnsibleを導入してから、以下OSやソフトウェアに対して作業のコード化や自動化を行ってきた。導入手順などは以下記事を参照。

OS/ソフトウェア URL
Linux AnsibleでLinuxサーバの初期設定と単体テストを行う
Windows Server AnsibleからWindows Serverに接続するための事前作業
vSphere ESXi AnsibleでESXi上に仮想マシンを構築する

今回は、Ansibleを使って仮想ルーターOSであるVyOSを操作する手順を記載する。VyOSは、Ansibleに標準で導入されているvyos.vyosというモジュールで操作可能となる。

環境

今回手順を確認した環境は以下の通り。

  • コントロールノード
    • OS : AlmaLinux 8.5
    • Ansible : ansible [core 2.13.1]
  • VyOS : 1.4

VyOSの各種設定を行うPlaybook

今回のPlaybookでは、VyOSに対して各種設定を行い、設定後にコンフィグをファイルとして保存する。

以下にPlaybookの内容を説明する。

Playbook説明

変数 (vars)

Ansibleを使ってVyOSを操作する際の変数は、以下の通り設定する。VyOSはCisco機器のようなansible_become_methodの設定値は不要となる。

変数 設定値
ansible_user 任意のSSH接続用ユーザを設定。今回はvyosで設定。
ansible_password 任意のSSH接続用ユーザのパスワードを設定。
ansible_connection network_cli
ansible_network_os vyos
vyos_interface インタフェースのdescriptionやIPアドレスを設定。
vyos_ntp_server 時刻同期先のNTPサーバを設定。
vyos_snmp SNMPに必要となるコミュニティ名やTrapターゲットを設定する。なお、TrapソースのIPアドレス指定する際に、vyos_interfaceの変数からIPアドレスを取得している。
vyos_route スタティックルートを設定。

タスク (tasks)

Playbookのタスクは以下の通り。主にvyos.vyosモジュールで個別に用意されている設定モジュールを使って設定可能なものをタスクとして作成した。これ以外の設定に関しては、vyos.vyos.vyos_configを使って、VyOSのコマンドを直接流して設定することができる(当然その際には冪等性には注意すること)。

タスク モジュール 説明
事前config保存(save) & configファイル取得 vyos.vyos.vyos_config VyOSのconfigを取得する。取得内容はshow configuration commandsの内容となる。また、configが保存されていないことを想定して、save: trueを設定する。
タイムゾーン設定 vyos.vyos.vyos_config タイムゾーンを設定する。タイムゾーンを設定するモジュールはないため、直接設定コマンドを実行する。
ホスト名設定 vyos.vyos.vyos_hostname ホスト名を設定する。
インタフェース設定 vyos.vyos.vyos_interfaces インタフェースのdescriptionを設定する。本来はIPアドレスもこのモジュールで設定できるが、次のタスクでIPv6を無効化する際に、IPアドレスの再設定が必要になることから、本タスクでは設定は省略している。
インタフェース設定 (IPアドレス設定 & IPv6 無効化) vyos.vyos.vyos_config IPアドレスとIPv6の無効化設定を直接コマンドにて設定する。
SSH & Console設定 vyos.vyos.vyos_config SSHとConsoleの設定を直接設定コマンドにて設定する
NTP設定 vyos.vyos.vyos_ntp_global NTPによる時刻同期先の設定を行う。
SNMP設定 vyos.vyos.vyos_snmp_server SNMPの設定を行う。SNMP Trapのターゲット設定は本モジュールでは動作に失敗したため、次のタスクにて直接コマンドにて設定する。
SNMP設定 (Trap target) vyos.vyos.vyos_config SNMP Trapのターゲット設定を直接コマンドにて設定する。
スタティックルート設定 vyos.vyos.vyos_static_routes スタティックルートを設定する。
事後config保存(save) & configファイル取得 vyos.vyos.vyos_config VyOSのconfigを取得する。
ファイル差分確認 ansible.builtin.command Linuxのdiffコマンドにて、設定前後のconfig比較を行う。
ファイル差分表示 ansible.builtin.debug diffコマンドの比較結果を表示する。

Playbook

以上をふまえ、Playbook全体は以下となる。

set_vyos_global_settings.yml

---
- name: Set vyos global settings
  gather_facts: true
  hosts: vyos

  vars:
    ansible_user: vyos
    ansible_password: 'P@ssw0rd!'
    ansible_connection: network_cli
    ansible_network_os: vyos

    vyos_interface:
      - name: eth0
        description: OUTSIDE
        address: 192.168.3.4
        prefix: 24
      - name: eth1
        description: INSIDE
        address: 192.168.1.4
        prefix: 24

    vyos_ntp_server:
      - server: 192.168.3.2

    vyos_snmp:
      community: public
      authorization_type: ro
      trap_source: '{{ (vyos_interface | selectattr("name", "==", "eth1") | first).address }}'
      trap_target: 192.168.1.24
      trap_community: public

    vyos_route:
      dest: 0.0.0.0/0
      next_hop: 192.168.3.254

  tasks:
    # 事前config保存(save) & configファイル取得
    - name: Get configuration command
      vyos.vyos.vyos_config:
        backup: true
        backup_options:
          dir_path: "{{ lookup('env', 'PWD') }}/vyos"
          filename: "{{ inventory_hostname }}_conf_before.log"
        save: true

    # タイムゾーン設定
    - name: Set timezone
      vyos.vyos.vyos_config:
        lines:
          - set system time-zone 'Asia/Tokyo'

    # ホスト名設定
    - name: Set hostname
      vyos.vyos.vyos_hostname:
        config:
          hostname: "{{ inventory_hostname }}"
        state: replaced

    # インタフェース設定
    - name: Set interfaces
      vyos.vyos.vyos_interfaces:
        config:
          - name: "{{ item.name }}"
            description: "{{ item.description }}"
        state: replaced
      loop: "{{ vyos_interface }}"

    # インタフェース設定 (IPアドレス設定 & IPv6 無効化)
    - name: Set interfaces ipv6 address
      vyos.vyos.vyos_config:
        lines:
          - set interfaces ethernet {{ item.name }} address {{ item.address }}/{{ item.prefix }}
          - set interfaces ethernet {{ item.name }} ipv6 address no-default-link-local
      loop: "{{ vyos_interface }}"

    # SSH & Console設定
    - name: Set SSH and consle
      vyos.vyos.vyos_config:
        lines:
          - set service ssh listen-address '{{ (vyos_interface | selectattr("name", "==", "eth1") | first).address }}'
          - delete system console

    # NTP設定
    - name: Set ntp server
      vyos.vyos.vyos_ntp_global:
        config:
          servers: "{{ vyos_ntp_server }}"
        state: replaced

    # SNMP設定
    # Trap targetは「requires a community to be set!」のエラーで失敗する
    # 設定をすべて置き換えをしないよう、state: mergedを指定
    - name: Set snmp
      vyos.vyos.vyos_snmp_server:
        config:
          communities:
            - name: "{{ vyos_snmp.community }}"
              authorization_type: "{{ vyos_snmp.authorization_type }}"
          trap_source: "{{ vyos_snmp.trap_source }}"
        state: merged

    # SNMP設定 (Trap target)
    - name: Set snmp trap target
      vyos.vyos.vyos_config:
        lines:
          - set service snmp trap-target {{ vyos_snmp.trap_target }} community {{ vyos_snmp.trap_community }}

    # スタティックルート設定
    - name: Set static route
      vyos.vyos.vyos_static_routes:
        config:
          - address_families:
              - afi: ipv4
                routes:
                  - dest: "{{ vyos_route.dest }}"
                    next_hops:
                      - forward_router_address: "{{ vyos_route.next_hop }}"
        state: replaced

    # 事後config保存(save) & configファイル取得
    - name: Get configuration command
      vyos.vyos.vyos_config:
        backup: true
        backup_options:
          dir_path: "{{ lookup('env', 'PWD') }}/vyos"
          filename: "{{ inventory_hostname }}_conf_after.log"
        save: true

    # ファイル差分確認
    # 差分があった場合も処理を継続するため、failed_when: falseを付与
    - name: Diff configuration
      ansible.builtin.command: |
        diff "vyos/{{ inventory_hostname }}_conf_before.log" "vyos/{{ inventory_hostname }}_conf_after.log"
      register: result
      changed_when: false
      delegate_to: localhost
      failed_when: false

    # ファイル差分表示
    - name: Show configuration differences
      ansible.builtin.debug:
        msg: "{{ result.stdout_lines }}"

実行結果

Playbookの実行結果は以下の通り。事前と事後でconfig比較を行い、設定差分がわかるようになっている。

# ansible-playbook -i hosts -l t3034vyos vyos/set_vyos_global_settings_sample.yml 

PLAY [Set vyos global settings] ********************************************************************************************************************************************

TASK [Gathering Facts] *****************************************************************************************************************************************************
ok: [t3034vyos]

TASK [Get configuration command] *******************************************************************************************************************************************
changed: [t3034vyos]

TASK [Set timezone] ********************************************************************************************************************************************************
[WARNING]: To ensure idempotency and correct diff the input configuration lines should be similar to how they appear if present in the running configuration on device
changed: [t3034vyos]

TASK [Set hostname] ********************************************************************************************************************************************************
changed: [t3034vyos]

TASK [Set interfaces] ******************************************************************************************************************************************************
changed: [t3034vyos] => (item={'name': 'eth0', 'description': 'OUTSIDE', 'address': '192.168.3.34', 'prefix': 24})
changed: [t3034vyos] => (item={'name': 'eth1', 'description': 'INSIDE', 'address': '192.168.1.34', 'prefix': 24})

TASK [Set interfaces ipv6 address] *****************************************************************************************************************************************
changed: [t3034vyos] => (item={'name': 'eth0', 'description': 'OUTSIDE', 'address': '192.168.3.34', 'prefix': 24})
changed: [t3034vyos] => (item={'name': 'eth1', 'description': 'INSIDE', 'address': '192.168.1.34', 'prefix': 24})

TASK [Set SSH and consle] **************************************************************************************************************************************************
changed: [t3034vyos]

TASK [Set ntp server] ******************************************************************************************************************************************************
changed: [t3034vyos]

TASK [Set snmp] ************************************************************************************************************************************************************
changed: [t3034vyos]

TASK [Set snmp trap target] ************************************************************************************************************************************************
changed: [t3034vyos]

TASK [Set static route] ****************************************************************************************************************************************************
changed: [t3034vyos]

TASK [Get configuration command] *******************************************************************************************************************************************
changed: [t3034vyos]

TASK [Diff configuration] **************************************************************************************************************************************************
ok: [t3034vyos -> localhost]

TASK [Show configuration differences] **************************************************************************************************************************************
ok: [t3034vyos] => {
    "msg": [
        "0a1,2",
        "> set interfaces ethernet eth0 address '192.168.3.4/24'",
        "> set interfaces ethernet eth0 description 'OUTSIDE'",
        "1a4",
        "> set interfaces ethernet eth0 ipv6 address no-default-link-local",
        "3a7",
        "> set interfaces ethernet eth1 description 'INSIDE'",
        "4a9",
        "> set interfaces ethernet eth1 ipv6 address no-default-link-local",
        "6c11,15",
        "< set service ssh",
        "---",
        "> set protocols static route 0.0.0.0/0 next-hop 192.168.3.254",
        "> set service snmp community public authorization 'ro'",
        "> set service snmp trap-source '192.168.1.4'",
        "> set service snmp trap-target 192.168.1.24 community 'public'",
        "> set service ssh listen-address '192.168.1.4'",
        "15,16c24",
        "< set system console device ttyS0 speed '115200'",
        "< set system host-name 'vyos'",
        "---",
        "> set system host-name 't3034vyos'",
        "18,20c26",
        "< set system ntp server time1.vyos.net",
        "< set system ntp server time2.vyos.net",
        "< set system ntp server time3.vyos.net",
        "---",
        "> set system ntp server 192.168.3.2",
        "22c28,29",
        "< set system syslog global facility protocols level 'debug'",
        "\\ ファイル末尾に改行がありません",
        "---",
        "> set system syslog global facility protocols level 'debug'",
        "> set system time-zone 'Asia/Tokyo'",
        "\\ ファイル末尾に改行がありません"
    ]
}

PLAY RECAP *****************************************************************************************************************************************************************
t3034vyos                  : ok=14   changed=11   unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

VyOSのconfigファイルも以下の通り出力される。

vyos/t3034vyos_conf_after.log

set interfaces ethernet eth0 address '192.168.3.4/24'
set interfaces ethernet eth0 description 'OUTSIDE'
set interfaces ethernet eth0 hw-id '00:0c:29:b8:da:49'
set interfaces ethernet eth0 ipv6 address no-default-link-local

~(以下略)~

以上で、Ansibleを使って仮想ルーターOSであるVyOSを操作する手順は完了となる。

2023年1月7日土曜日

「minikube」を使ってKubernetes検証環境を構築する手順

コンテナのオーケストレーションツールのデファクトスタンダードとなっているKubernetesは、仕組みが複雑であり、マニュアルや書籍を見るだけでは、なかなか理解を深めるのが難しい。

インフラ技術を理解するためには、実際に構築して操作することが一番早いと考えており、自宅検証環境にKubernetes環境を構築することにした。

今回は、Linux OS上に容易にKubernetes検証環境を構築できる「minikube」をインストールする手順を記載する。また、minikube起動後に、簡単なコンテナを作成し外部からアクセスするまでの流れを確認してみよう。

環境

以下に今回構築する各種ソフトウェアのバージョンを記載する。

  • ホストOS : AlmaLinux 8.6 (GUI環境を含めインストールする)
  • ホストDocker : 20.10.21
  • minikube : 1.28.0

minikubeを動作させるためのリソース要件は以下の通り。今回は、CPU 4コア、メモリ 4GB、ディスク 20GBで構成した。また、インターネット接続はプロキシ(私の環境の場合はhttp://192.168.33.23:8080)経由での接続が必要となるため、必要なプロキシ設定も手順に記載している。プロキシ設定が不要な場合は、手順を飛ばしてもらえれば問題ない。

  • 2 CPUs or more
  • 2GB of free memory
  • 20GB of free disk space
  • Internet connection

minikubeはホストOSのDockerやVirtualBoxを用いて、Kubernetesのノードを構成することで、Kubernetes環境を即座にスクラップ&ビルドしながら検証をすることができる。

以下にminikubeの環境の構成概要図を記載する。

minikubeインストール手順

1. プロキシ設定 (必要な場合のみ)

私の環境ではプロキシ経由でなければインターネット接続ができないため、以下の通り環境変数を設定する。プロキシの環境変数について小文字と大文字の両方を設定している理由は、dnfコマンドでは小文字の環境変数の設定が必要であり、minikubeの場合は大文字の環境変数の設定が必要となるためである(とてもややこしい)。

# export http_proxy=http://192.168.33.23:8080
# export https_proxy=http://192.168.33.23:8080
# export no_proxy=192.168.0.0/16
# export HTTP_PROXY=http://192.168.33.23:8080
# export HTTPS_PROXY=http://192.168.33.23:8080
# export NO_PROXY=192.168.0.0/16

2. Dockerインストール前の競合パッケージの削除

minikubeはノードをDockerコンテナやVirtualBoxの仮想マシンとして構築する。今回はDockerをドライバーとして利用することとし、まずは、Dockerをインストールする。

ただし、GUI環境をインストールしたAlmaLinuxの場合、以下の通りpodmanとcontainers-commonのパッケージが競合する旨のエラーでインストールに失敗する。

# dnf install docker-ce docker-ce-cli containerd.io -y
メタデータの期限切れの最終確認: 0:05:01 時間前の 2022年11月26日 12時46分04秒 に 実施しました。
エラー:
 問題 1: インストール済パッケージの問題 podman-2:4.0.2-6.module_el8.6.0+2878+e681bc44.x86_64
  - パッケージ podman-2:4.0.2-6.module_el8.6.0+2878+e681bc44.x86_64 には runc >= 1.0.0-57 が必要ですが、どのプロバイダーからもインストールできません
  - パッケージ podman-3:4.2.0-4.module_el8.7.0+3344+484dae7b.x86_64 には runc >= 1.0.0-57 が必要ですが、どのプロバイダーからもインストールできません

~(中略)~

 問題 2: インストール済パッケージの問題 containers-common-2:1-27.module_el8.6.0+2878+e681bc44.x86_64
  - パッケージ containers-common-2:1-27.module_el8.6.0+2878+e681bc44.x86_64 には runc が必要ですが、どのプロバイダーからもインストールできません
  - パッケージ containers-common-2:1-43.module_el8.7.0+3344+484dae7b.x86_64 には runc が必要ですが、どのプロバイダーからもインストールできません

~(中略)~

このような場合は、一度podmanとcontainers-commonのパッケージを削除したうえで、Dockerをインストールしよう。

# dnf remove podman containers-common

3. Dockerをインストール

Dockerのインストールは以下の通りコマンドを実行すればよい。

# dnf install yum-utils -y
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# dnf install docker-ce docker-ce-cli containerd.io -y

プロキシ環境の場合は、外部からコンテナのダウンロードができるよう、systemctlの起動設定に環境変数の設定をしておくこと。

# sed -ie '/\[Service\]/a Environment="http_proxy=http://192.168.33.23:8080" "https_proxy=http://192.168.33.23:8080" "no_proxy=192.168.0.0/16"' /usr/lib/systemd/system/docker.service

インストール完了後、Dockerのサービスを起動しておく。

# systemctl start docker
# systemctl enable docker

4. minikubeインストール

minikubeのインストールは、rpmをダウンロードしインストールするだけで完了する。

# curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-latest.x86_64.rpm
# rpm -Uvh minikube-latest.x86_64.rpm

5. minikube操作用ユーザの作成

minikubeのDockerドライバーはroot権限で操作できないため、操作用ユーザを作成する。参考情報として、もしroot権限でminikubeを起動すると、以下のようなメッセージが表示され、起動に失敗する。

X DRV_AS_ROOT が原因で終了します: 「docker」ドライバーは root 権限で使用すべきではありません。

今回はkubeuserというユーザを作成した。また、sudoが必要なコマンドがあるためwheelグループへの所属と、Dockerドライバーを操作するためにdockerグループへ所属させておく。

# useradd kubeuser
# usermod -aG wheel,docker kubeuser
# id kubeuser
uid=1000(kubeuser) gid=1000(kubeuser) groups=1000(kubeuser),10(wheel),974(docker)

6. minikubeを起動

以上で準備が整ったため、kubeuserにスイッチし、minikube startコマンドでminikubeを起動する。初回は、800MBほどのコンテナイメージのダウンロードが行われるため、時間を要するので気長に待とう。

# su - kubeuser

$ minikube start
* Almalinux 8.6 上の minikube v1.28.0
* docker ドライバーが自動的に選択されました
* root 権限を持つ Docker ドライバーを使用
* minikube クラスター中のコントロールプレーンの minikube ノードを起動しています
* ベースイメージを取得しています...
* ロード済み Kubernetes v1.25.3 をダウンロードしています...
    > preloaded-images-k8s-v18-v1...:  385.44 MiB / 385.44 MiB  100.00% 77.08 M
    > gcr.io/k8s-minikube/kicbase:  386.27 MiB / 386.27 MiB  100.00% 13.86 MiB
    > gcr.io/k8s-minikube/kicbase:  0 B [________________________] ?% ? p/s 24s
* docker container (CPUs=2, Memory=2200MB) を作成しています...
* ネットワークオプションが見つかりました:
  - HTTP_PROXY=http://192.168.33.23:8080
  - HTTPS_PROXY=http://192.168.33.23:8080
  - NO_PROXY=192.168.0.0/16
* Docker 20.10.20 で Kubernetes v1.25.3 を準備しています...
  - env HTTP_PROXY=http://192.168.33.23:8080
  - env HTTPS_PROXY=http://192.168.33.23:8080
  - env NO_PROXY=192.168.0.0/16
  - 証明書と鍵を作成しています...
  - コントロールプレーンを起動しています...
  - RBAC のルールを設定中です...
* Kubernetes コンポーネントを検証しています...
  - gcr.io/k8s-minikube/storage-provisioner:v5 イメージを使用しています
* 有効なアドオン: default-storageclass, storage-provisioner
* kubectl が見つかりません。kubectl が必要な場合、'minikube kubectl -- get pods -A' を試してください
* 終了しました!kubectl がデフォルトで「minikube」クラスターと「default」ネーム スペースを使用するよう設定されました

7. kubectlコマンドのエイリアスを設定

Kubernetes環境を操作するためのkubectlコマンドはminikubeには用意されておらず、minikube kubectl -- [コマンド]といったコマンドを実行する必要がある。

コマンドの簡略化と本来のKubernetes環境の操作に近づけることを目的として、エイリアスを設定しておく。

$ echo 'alias kubectl="minikube kubectl --"' >> ~/.bashrc
$ source ~/.bashrc

8. 起動状態の確認

minikube起動後のノードとPodの状態を確認しておこう。

ノードは通常1台のみ起動しているはずだ。詳細は省くが、minikubeをマルチノード構成としたい場合は、minikube start --nodes=3といった形でノード数を指定することで、複数ノードで起動させることができる。

$ kubectl get node -o=wide
NAME       STATUS   ROLES           AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION              CONTAINER-RUNTIME
minikube   Ready    control-plane   10m   v1.25.3   192.168.49.2   <none>        Ubuntu 20.04.5 LTS   4.18.0-372.9.1.el8.x86_64   docker://20.10.20

PodとしてはKubernetes環境管理に必要となる各種Podが起動する。ステータスがRunningになっていれば問題ない。

$ kubectl get pod -A
NAMESPACE     NAME                               READY   STATUS    RESTARTS       AGE
kube-system   coredns-565d847f94-t7f4s           1/1     Running   0              2m22s
kube-system   etcd-minikube                      1/1     Running   0              2m35s
kube-system   kube-apiserver-minikube            1/1     Running   0              2m35s
kube-system   kube-controller-manager-minikube   1/1     Running   0              2m35s
kube-system   kube-proxy-2jzrw                   1/1     Running   0              2m22s
kube-system   kube-scheduler-minikube            1/1     Running   0              2m35s
kube-system   storage-provisioner                1/1     Running   1 (112s ago)   2m34s

動作確認

Kubernetesの動作確認としてにテスト用のコンテナを用いてPodを作成し、サービスとして公開してみよう。

再掲となるが、動作確認時におけるminikubeの内部構成は以下の図のようになる。

1. Podとサービスの起動確認

以下コマンドでPodを作成する。

$ kubectl create deployment hello-minikube --image=kicbase/echo-server:1.0
deployment.apps/hello-minikube created

$ kubectl get pod -o=wide
NAME                              READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
hello-minikube-7ddcbc9b8b-5g79b   1/1     Running   0          12s   172.17.0.3   minikube   <none>           <none>

作成したPodはそのままでは外部からアクセスすることができないため、Podと紐づけるサービスを作成する。なお、--type=NodePortを指定することで、ノードの持つIPアドレス(192.168.49.2)にてサービスを公開することができる。

$ kubectl expose deployment hello-minikube --type=NodePort --port=8080
service/hello-minikube exposed

$ kubectl get service -o=wide
NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE    SELECTOR
hello-minikube   NodePort    10.107.255.240   <none>        8080:31931/TCP   7s     app=hello-minikube
kubernetes       ClusterIP   10.96.0.1        <none>        443/TCP          102s   <none>

公開したサービスにアクセスしてみよう。ホストOSのブラウザを開いて、直接URLを入力してもよいが、minikubeコマンドを使用することで、サービスのURLを入力した状態でデフォルトのブラウザを起動させることができる。

$ minikube service hello-minikube
|-----------|----------------|-------------|---------------------------|
| NAMESPACE |      NAME      | TARGET PORT |            URL            |
|-----------|----------------|-------------|---------------------------|
| default   | hello-minikube |          80 | http://192.168.49.2:31931 |
|-----------|----------------|-------------|---------------------------| * デフォルトブラウザーで default/hello-minikube サービスを開いています... http://192.168.49.2:31931

2. 外部からサービスにアクセスさせるためのポートフォワード設定

minikubeのサービスに対しては、通常ホストOSでなければアクセスすることができないが、もし外部からアクセスさせたい場合は、以下の通りポートフォワードすることで実現できる。

なお、ポートフォワードはフォアグラウンドで実行されるため、終了する際はCtrl + Cで終了させること。

$ kubectl port-forward service/hello-minikube --address 0.0.0.0 8080:8080
Forwarding from 0.0.0.0:8080 -> 8080
Handling connection for 8080
Handling connection for 8080
^C ←★Ctrl + Cでプロセス終了

この状態の場合は、以下の通り外部からホストOSのIPアドレス(今回は192.168.11.52)でサービスにアクセスすることができる。

ポートフォワードをバックグラウンド実行させる場合は、以下の通り実行する。

$ kubectl port-forward service/hello-minikube --address 0.0.0.0 7080:80 > /dev/null 2>&1 &
[1] 33173

$ fg
minikube kubectl -- port-forward service/hello-minikube --address 0.0.0.0 7080:80 > /dev/null 2>&1
^C ←★Ctrl + Cでプロセス終了

以上で、Linux OS上に「minikube」をインストールする手順は完了となる。

minikube環境をリセットする

最後にminikube環境をリセットする方法を紹介しておこう。環境の削除は、minikube deleteコマンドを実行するだけで完了する。

$ minikube delete
  docker の「minikube」を削除しています...
  コンテナー「minikube」を削除しています...
  /home/kubeuser/.minikube/machines/minikube を削除しています...
  クラスター「minikube」の全てのトレースを削除しました。

削除後に再度minikube startすることで、再度きれいな状態でminikubeのKubernetes環境を利用することができる。

参考

2022年12月28日水曜日

OSSのコンテナレジストリ「Harbor」インストール手順

Docker Hubのようにコンテナイメージを格納し、Dockerにてイメージをダウンロード(Pull)して利用できるようにするサービスをコンテナリポジトリと呼ぶ。

Docker Hubはインターネット上で公開されたサービスとなり、誰でも自由に使える一方、インターネット環境であることからセキュリティ面におけるリスクも大きい。

そのような状況をふまえ、自宅検証環境にプライベートのコンテナレジストリを構築することにした。本記事では、OSSのコンテナレジストリ「Harbor」をインストールする手順を記載する。

なお、今回はHarborへのアクセスをHTTPによる構成としたが、自己署名証明書を使ってHTTPSにて通信させる場合は、以下記事を参照いただきたい。

環境

Harbor自体はDockerコンテナとして動作する。Harbor及びDockerが動作するOSとしてはAlmaLinuxを使用した。

  • OS : AlmaLinux release 8.6
  • Docker : 20.10.21
  • Docker Compose : v2.12.2
  • Harbor : v2.6.2
今回の作業の簡単な概要図を以下に記載する。

Dockerインストール

1. Dockerインストール

Harbor自体もDockerコンテナとして動作するため、まずはDockerのインストールを行う。

# dnf install yum-utils -y
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# dnf install docker-ce docker-ce-cli containerd.io -y

プロキシ環境の場合は、インターネット接続できるようにsystemdに環境変数の設定を行う。

# sed -ie '/\[Service\]/a Environment="http_proxy=http://192.168.33.23:8080" "https_proxy=http://192.168.33.23:8080" "no_proxy=192.168.0.0/16"' /usr/lib/systemd/system/docker.service
# systemctl start docker
# systemctl enable docker

2. Docker composeのインストール

Harborはインストール時にDocker composeを利用するため、こちらもインストールする。Docker composeは以下の通りdnfコマンドでインストールすることができる。

# dnf install docker-compose-plugin -y

Docker composeのバージョンを確認しておく。

# docker compose version
Docker Compose version v2.12.2

本題とは逸れるが、Docker composeはもともとdocker-composeといったコマンド体系となっていたが、現在のDocker compose V2系では、dockerコマンドに統合されており、docker composeというハイフンなしのコマンド体系になっている。たとえば、docker-compose up -ddocker compose up -dで実行する必要があるので覚えておくとよいだろう。

Compose V2 integrates compose functions into the Docker platform, continuing to support most of the previous docker-compose features and flags. You can run Compose V2 by replacing the hyphen (-) with a space, using docker compose, instead of docker-compose.

Harborインストール

1. Harborのインストーラをダウンロード

Harborのインストーラは、オンラインインストーラとオフラインインストーラの2種類が用意されている。今回はオフラインインストーラを用いる。ダウンロードは以下URLからダウンロードすることができる。

名前に-rcN(Nは数字1桁)が付与されているものは、リリース候補版となる。今回はlatestタグの付与されているバージョン2.6.2をインストールすることにした。オフラインインストーラの容量は約760MBとなる。

2. インストーラを解凍

インストーラはtgz圧縮されているので解凍する。ファイル容量は大きいが、ファイル数自体は多くない。

# tar zxvf harbor-offline-installer-v2.6.2.tgz
harbor/harbor.v2.6.2.tar.gz
harbor/prepare
harbor/LICENSE
harbor/install.sh
harbor/common.sh
harbor/harbor.yml.tmpl

# ls -l harbor
合計 792320
-rw-r--r-- 1 root root     11347 11月  9 18:35 LICENSE
-rw-r--r-- 1 root root      3639 11月  9 18:35 common.sh
-rw-r--r-- 1 root root 811298774 11月  9 18:36 harbor.v2.6.2.tar.gz
-rw-r--r-- 1 root root     10649 11月  9 18:35 harbor.yml.tmpl
-rwxr-xr-x 1 root root      3171 11月  9 18:35 install.sh
-rwxr-xr-x 1 root root      1881 11月  9 18:35 prepare

3. インストール設定ファイル(YAML)を修正

Harborはインストールの設定ファイルとして、harbor.ymlというYAMLファイルの作成が必要となる。

解凍したインストーラ内部に、harbor.yml.tmplというテンプレートが存在するため、これをコピーしてharbor.ymlを作成する。

# cd harbor
# cp harbor.yml.tmpl harbor.yml

以下★箇所を最低限設定しておく。通常Harborへの接続としては、セキュリティの観点からHTTP通信ではなくHTTPS通信を使用すべきであるが、今回は手順簡略化のためHTTP通信による設定を行う。

その他のパラメータについては、公式ドキュメントを参照いただきたい。

harbor.yml

# Configuration file of Harbor

# The IP address or hostname to access admin UI and registry service.
# DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.
hostname: 192.168.11.54 ←★ホスト名を設定する。DNSなどで名前解決できる場合はFQDN設定が望ましいが、今回はIPアドレスで設定する

# http related config
http:
  # port for http, default is 80. If https enabled, this port will redirect to https port
  port: 80

# https related config
#https: ←★原則はHTTPSによる通信が望ましいが、今回は手順簡略化のためHTTPを使用するためコメントアウト
  # https port for harbor, default is 443
#  port: 443 ←★原則はHTTPSによる通信が望ましいが、今回は手順簡略化のためHTTPを使用するためコメントアウト
  # The path of cert and key files for nginx
#  certificate: /your/certificate/path ★←SSLサーバ証明書を使用しないためコメントアウト
#  private_key: /your/private/key/path ★←SSLサーバ証明書を使用しないためコメントアウト

~(以下略)~

4. インストールスクリプトの実行

harbor.ymlの準備が整ったら、インストールスクリプトを実行する。[Step 0]から[Step 5]まで処理が順に実行される。最後の[Step 5]において、Docker composeによるコンテナ起動がされていることがわかる。

# ./install.sh

[Step 0]: checking if docker is installed ...

Note: docker version: 20.10.21

[Step 1]: checking docker-compose is installed ...

Note: Docker Compose version v2.12.2

[Step 2]: loading Harbor images ...
Loaded image: goharbor/harbor-jobservice:v2.6.2
Loaded image: goharbor/trivy-adapter-photon:v2.6.2
Loaded image: goharbor/chartmuseum-photon:v2.6.2
Loaded image: goharbor/redis-photon:v2.6.2
Loaded image: goharbor/nginx-photon:v2.6.2
Loaded image: goharbor/notary-signer-photon:v2.6.2
Loaded image: goharbor/harbor-core:v2.6.2
Loaded image: goharbor/harbor-db:v2.6.2
Loaded image: goharbor/harbor-registryctl:v2.6.2
Loaded image: goharbor/harbor-exporter:v2.6.2
Loaded image: goharbor/prepare:v2.6.2
Loaded image: goharbor/registry-photon:v2.6.2
Loaded image: goharbor/notary-server-photon:v2.6.2
Loaded image: goharbor/harbor-portal:v2.6.2
Loaded image: goharbor/harbor-log:v2.6.2


[Step 3]: preparing environment ...

[Step 4]: preparing harbor configs ...
prepare base dir is set to /root/harbor
WARNING:root:WARNING: HTTP protocol is insecure. Harbor will deprecate http protocol in the future. Please make sure to upgrade to https
Generated configuration file: /config/portal/nginx.conf
Generated configuration file: /config/log/logrotate.conf
Generated configuration file: /config/log/rsyslog_docker.conf
Generated configuration file: /config/nginx/nginx.conf
Generated configuration file: /config/core/env
Generated configuration file: /config/core/app.conf
Generated configuration file: /config/registry/config.yml
Generated configuration file: /config/registryctl/env
Generated configuration file: /config/registryctl/config.yml
Generated configuration file: /config/db/env
Generated configuration file: /config/jobservice/env
Generated configuration file: /config/jobservice/config.yml
Generated and saved secret to file: /data/secret/keys/secretkey
Successfully called func: create_root_cert
Generated configuration file: /compose_location/docker-compose.yml
Clean up the input dir


Note: stopping existing Harbor instance ...


[Step 5]: starting Harbor ...
[+] Running 10/10
 ? Network harbor_harbor        Created                                    0.0s
 ? Container harbor-log         Started                                    0.3s
 ? Container harbor-db          Started                                    0.9s
 ? Container registry           Started                                    1.0s
 ? Container registryctl        Started                                    0.9s
 ? Container harbor-portal      Started                                    1.0s
 ? Container redis              Started                                    1.0s
 ? Container harbor-core        Started                                    1.4s
 ? Container nginx              Started                                    2.2s
 ? Container harbor-jobservice  Started                                    2.1s
? ----Harbor has been installed and started successfully.----

もし、インストールスクリプト実行後にharbor.ymlを修正した場合は、再度インストールスクリプトを実行することで設定反映ができる。再実行の場合は、一度コンテナが削除されたのち、新しいコンテナが起動される。

# ./install.sh

[Step 0]: checking if docker is installed ...

Note: docker version: 20.10.21

[Step 1]: checking docker-compose is installed ...

Note: Docker Compose version v2.12.2

~(中略)~

Note: stopping existing Harbor instance ...
[+] Running 10/9
 ? Container nginx              Removed                                    0.1s
 ? Container harbor-jobservice  Removed                                    0.1s
 ? Container registryctl        Removed                                   10.1s
 ? Container harbor-portal      Removed                                    0.1s
 ? Container harbor-core        Removed                                    0.1s
 ? Container redis              Removed                                    0.3s
 ? Container harbor-db          Removed                                    0.3s
 ? Container registry           Removed                                    0.3s
 ? Container harbor-log         Removed                                   10.1s
 ? Network harbor_harbor        Removed                                    0.0s


[Step 5]: starting Harbor ...
[+] Running 10/10
 ? Network harbor_harbor        Created                                    0.0s
 ? Container harbor-log         Started                                    0.3s
 ? Container registryctl        Started                                    0.6s
 ? Container harbor-portal      Started                                    1.1s
 ? Container registry           Started                                    1.0s
 ? Container redis              Started                                    1.1s
 ? Container harbor-db          Started                                    1.0s
 ? Container harbor-core        Started                                    1.2s
 ? Container harbor-jobservice  Started                                    1.7s
 ? Container nginx              Started                                    1.7s
? ----Harbor has been installed and started successfully.----

5. DockerをHTTP接続に対応させる設定

Dockerは標準では、コンテナレジストリに対してHTTPSによる接続を行うため、HTTPによる接続をできるよう、/etc/docker/daemon.jsonのファイルを新規作成する。

記載しているIPアドレスは、harbor.ymlhostnameの設定と合わせればよく、IPアドレスまたはFQDNで設定することができる。

# ls -l /etc/docker/daemon.json
ls: '/etc/docker/daemon.json' にアクセスできません: そのようなファイルやディレクトリはありません
# cat << EOF > /etc/docker/daemon.json
{
  "insecure-registries": [
    "192.168.11.54"
  ]
}
EOF

設定後は、Docker及びHarborの再起動が必要となるため、以下の通り再起動を行う。

# systemctl restart docker
# docker compose down -v
# docker compose up -d

6. Web管理画面にログイン

HarborのWeb管理画面にログインする。

  • ユーザ : admin
  • 初期パスワード : Harbor12345
  • 接続先 : http://[HarborをインストールしたOSのIPアドレス]

動作確認

1. プロジェクトを作成

Harborではプロジェクトを作成し、そこにコンテナイメージを保存して管理する構成となっている。デフォルトでlibraryという名称のプロジェクトが存在するが、今回はあえて新規にmyprojectという名称のプロジェクトを作成した。

プロジェクトを作成の際の設定値は以下の通り。

設定項目 設定値 説明
Project Name myproject 任意の名前で設定する。
Access Level Public アクセス権はPublicとする。Publicの場合は、Pullする際にdocker loginコマンドによる認証が不要となる。逆にPublicにしない場合(Privateにする場合)は、Pullの際にdocker loginコマンドによる認証が必要となる。なお、Pushの際はいずれの権限においても事前の認証が必要となる。
Storage Quota -1 GiB 容量の制限(クォータ)の設定となる。今回はデフォルトの無制限(-1)とする。
Proxy Cache 無効 プロキシキャッシュの機能は無効化する。プロキシキャッシュの詳細は、公式マニュアルを参照いただきたい。

2. テスト用コンテナイメージのPull

それでは、Harborを使ってコンテナイメージのアップロード(Push)とダウンロード(Pull)ができることを確認しよう。なお、Push及びPullを行うDockerは、Harborとは別のサーバにインストールしたものとする。

テスト用のコンテナイメージはoraclelinux:8.7を用いる。このコンテナイメージをHarborへPushし、その後一度コンテナイメージを削除してから、HarborよるPullできることを確認する。

まずは、oraclelinux:8.7のコンテナイメージをDocker HubよりPullする。

# docker pull oraclelinux:8.7
8.7: Pulling from library/oraclelinux
4c770e098606: Pull complete
Digest: sha256:07a995ecaf9db1ce613648a08facc162de69f26c39712f1acc93629c2e6c4e73
Status: Downloaded newer image for oraclelinux:8.7
docker.io/library/oraclelinux:8.7

# docker images
REPOSITORY    TAG       IMAGE ID       CREATED       SIZE
oraclelinux   8.7       b0045ea7bbde   10 days ago   225MB

3. DockerをHTTP接続に対応させる設定

Dockerは標準では、コンテナレジストリに対してHTTPSによる接続を行うため、HTTPによる接続をできるよう、/etc/docker/daemon.jsonのファイルを新規作成する。

# ls -l /etc/docker/daemon.json
ls: '/etc/docker/daemon.json' にアクセスできません: そのようなファイルやディレクトリはありません
# cat << EOF > /etc/docker/daemon.json
{
  "insecure-registries": [
    "192.168.11.54"
  ]
}
EOF

設定後は、Dockerの再起動が必要となるため、以下の通り再起動を行う。

# systemctl restart docker

4. Harborへの認証

Pushする場合は、事前にdocker loginコマンドにてHarborに対して認証を成功させておく必要がある。ここで入力するユーザ名とパスワードは、Web管理画面と同じadmin / Harbor12345となる。

# docker login 192.168.11.54
Username: admin
Password: ←★"Harbor12345"を入力
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

5. コンテナイメージをPush

Pushするコンテナイメージに対して、タグの設定を行う。タグは以下の形式で設定する。

[HarborのIPアドレスまたはFQDN]/[プロジェクト名]:[タグ名]

実行結果を以下に記載する。

# docker tag oraclelinux:8.7 192.168.11.54/myproject/oraclelinux:8.7
# docker images
REPOSITORY                            TAG       IMAGE ID       CREATED       SIZE
192.168.11.54/myproject/oraclelinux   8.7       b0045ea7bbde   10 days ago   225MB
oraclelinux                           8.7       b0045ea7bbde   10 days ago   225MB

タグを付与したコンテナイメージをPushする。

# docker push 192.168.11.54/myproject/oraclelinux:8.7
The push refers to repository [192.168.11.54/myproject/oraclelinux]
d8c569c85182: Pushed
8.7: digest: sha256:89787c72978339a100b1855de3ab7749f29752fc83302456bfac6ba209008401 size: 529

特に問題が発生しなければ、HarborのWeb管理画面からも、Pushしたコンテナイメージを確認することができるはずだ。

6. コンテナイメージを削除

次に、先ほどPushしたコンテナイメージをPullしてみよう。

まずは、ローカルに存在するコンテナイメージを削除する。

# docker images
REPOSITORY                            TAG       IMAGE ID       CREATED       SIZE
192.168.11.54/myproject/oraclelinux   8.7       b0045ea7bbde   10 days ago   225MB
oraclelinux                           8.7       b0045ea7bbde   10 days ago   225MB

# docker rmi b0045ea7bbde -f
Untagged: 192.168.11.54/myproject/oraclelinux:8.7
Untagged: 192.168.11.54/myproject/oraclelinux@sha256:89787c72978339a100b1855de3ab7749f29752fc83302456bfac6ba209008401
Untagged: oraclelinux:8.7
Untagged: oraclelinux@sha256:07a995ecaf9db1ce613648a08facc162de69f26c39712f1acc93629c2e6c4e73
Deleted: sha256:b0045ea7bbde263d0543ac9efb749e588d3538bc673f98fe00a73006838a9b89
Deleted: sha256:d8c569c851824688f0f55d46d659a8eef6b8af3ed0a20f389b066f16a4a250e5

# docker images
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE

7. HarborよりコンテナイメージをPull

HarborよりコンテナイメージをPullする。

# docker pull 192.168.11.54/myproject/oraclelinux:8.7
8.7: Pulling from myproject/oraclelinux
4c770e098606: Pull complete
Digest: sha256:89787c72978339a100b1855de3ab7749f29752fc83302456bfac6ba209008401
Status: Downloaded newer image for 192.168.11.54/myproject/oraclelinux:8.7
192.168.11.54/myproject/oraclelinux:8.7

# docker images
REPOSITORY                            TAG       IMAGE ID       CREATED       SIZE
192.168.11.54/myproject/oraclelinux   8.7       b0045ea7bbde   10 days ago   225MB

Pullに成功すると、Harbor上でもPullが実行された回数が更新される。

以上で、OSSのコンテナレジストリ「Harbor」をインストールする手順は完了となる。

参考

人気の投稿