无法通过 ssh 连接到主机:权限被拒绝

Failed to connect to the host via ssh: Permission denied

我是ansible的新手 我在 ec2 实例上安装了 ansible(作为主虚拟机) 现在我想将我的目标节点设置为 gcp vm 为此,我创建了一个 gcp 虚拟机并更新了清单文件

ansible-target ansible_host=gcp_vm_ip ansible_connection=ssh ansible_user=apigeehybrid

但是当我 运行 ansible ansible-target -m ping 我收到错误

<35.184.210.81> ESTABLISH SSH CONNECTION FOR USER: apigeehybrid
<35.184.210.81> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="apigeehybrid"' -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/ef74ba60db 35.184.210.80 '/bin/sh -c '"'"'echo ~apigeehybrid && sleep 0'"'"''
<35.184.210.81> (255, '', 'Permission denied (publickey,gssapi-keyex,gssapi-with-mic).\r\n')
target-aio | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).", 
    "unreachable": true
}

现在我知道我必须使用 SSH 密钥,但我有点困惑,因为我尝试了很多创建密钥的方法并放在某个地方,但这对我来说不起作用

谁能详细说明建立连接的完美设置 b/w master vm(ec2) to target vm(gcp instance) 那太好了...

Terraform X Apigee 集成 架构是相同的,但我在 ec2

的主虚拟机中创建了一个 node.tf 文件
resource "google_compute_network" "default" {
  name = "my-network"
}

resource "google_compute_subnetwork" "default" {
  name          = "my-subnet"
  ip_cidr_range = "10.0.0.0/16"
  region        = "us-central1"
  network       = google_compute_network.default.id
}

resource "google_compute_address" "internal_ip" {
  name         = "my-internal-address"
  project      = var.projectname
  subnetwork   = google_compute_subnetwork.default.id
  address_type = "INTERNAL"
  address      = "10.0.1.0"
  region       = "us-central1"
  purpose      = "GCE_ENDPOINT"
}

resource "google_compute_address" "static" {
  name    = "vm-public-address"
  project = var.projectname
  region  = "us-central1"
}

resource "google_compute_firewall" "firewall2" {
  name    = "gritfy-firewall-externalssh2"
  network = google_compute_network.default.name
  allow {
    protocol = "tcp"
    ports    = ["22"]
  }
  source_ranges = ["0.0.0.0/0"]
}

output "ip1" {
  value = google_compute_address.static.address
}

resource "google_compute_instance" "node1" {
  project        = var.projectname
  name           = "node1"
  machine_type   = "custom-8-16384" //10 core and 20GB of ram custom-10-20480
  zone           = "us-central1-a"
  can_ip_forward = true
  boot_disk {
    initialize_params {
      image = "centos-cloud/centos-7"
    }
  }
  network_interface {
    subnetwork = google_compute_subnetwork.default.id
    network_ip = google_compute_address.internal_ip.address
    access_config {
      nat_ip = google_compute_address.static.address
    }
  }
  metadata = {
    ssh-keys = "${var.user}:${file(var.publickeypath)}"
  }
  lifecycle {
    ignore_changes = [attached_disk]
  }
  provisioner "file" {
    source      = "perquisites.sh"
    destination = "/tmp/perquisites.sh"
    connection {
      host        = google_compute_address.static.address
      type        = "ssh"
      user        = var.user
      private_key = file(var.privatekeypath)
    }
  }
  provisioner "local-exec" {
    command = "echo ${google_compute_address.static.address} > inventory "
  }
  provisioner "local-exec" {
    command = "ssh-keygen -R ${google_compute_address.static.address}"
  }
  provisioner "local-exec" {
    command = "ansible-playbook /root/playbooks/aio.yaml"
  }
}

resource "google_compute_attached_disk" "default3" {
  disk     = google_compute_disk.default2.id
  instance = google_compute_instance.node1.id
}

resource "google_compute_disk" "default2" {
  name  = "disk1"
  type  = "pd-balanced"
  zone  = "us-central1-a"
  image = "centos-7-v20210609"
  size  = 100 //in GBs 300
}

这是ansible.cfg文件

[defaults]
inventory = ./inventory
deprecation_warnings=False
remote_user = rohan
host_key_checking = False
private_key_file = ./lastkey

[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = False

如果有人在 terraform 代码中注意到我使用了 remote-exec 并且它正在工作,我可以看到显示已连接的日志

但在 ansible 中,它显示

根据您给我们的信息和您提供的错误信息(Permission denied (publickey,gssapi-keyex,gssapi-with-mic)),您需要create a SSH key pair

ssh-keygen -t ed25519 -f ~/.ssh/<KEY_FILENAME> -C <USER>

(有关选项的完整列表,请参阅:https://man.openbsd.org/ssh-keygen

然后将 PUBLIC KEY(不是私钥)添加到 GCE 实例上的 apigeehybrid 用户,手动将其放入 ~apigeehybrid/.ssh/authorized_keys 文件或 GCP native ways 中:

OS 登录

gcloud compute os-login ssh-keys add \
    --key-file=KEY_FILE_PATH \
    --project=PROJECT \
    --ttl=EXPIRE_TIME

元数据

运行 gcloud compute instances describe 命令获取虚拟机的元数据:

gcloud compute instances describe VM_NAME

将 VM_NAME 替换为您需要为其添加或删除 public SSH 密钥的 VM 的名称。

输出类似于以下内容:

...
metadata:
...
- key: ssh-keys
  value: |-
    cloudysanfrancisco:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDAu5kKQCPF...
    baklavainthebalkans:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQDx3FNVC8... google-ssh {"userName":"baklavainthebalkans","expireOn":"2021-06-14T16:59:03+0000"}
...

复制 ssh-keys 元数据值。

在您的工作站上创建并打开一个新的文本文件。

在文件中,粘贴您刚刚复制的密钥列表。

在列表末尾添加您的新密钥,采用以下格式之一:

没有过期时间的密钥格式:

USERNAME:KEY_VALUE

带有过期时间的密钥格式:

USERNAME:KEY_VALUE google-ssh {"userName":"USERNAME","expireOn":"EXPIRE_TIME"}

替换以下内容:

KEY_VALUE:public SSH 密钥值

USERNAME:SSH 密钥的用户名,在创建密钥时指定

EXPIRE_TIME:key过期时间,ISO 8601格式。例如:2021-12-04T20:12:00+0000

保存并关闭文件。

运行 gcloud compute instances add-metadata命令设置ssh-keys值:

gcloud compute instances add-metadata VM_NAME --metadata-from-file ssh-keys=KEY_FILE

替换以下内容:

VM_NAME:您要为其添加 SSH 密钥的虚拟机

KEY_FILE 满足以下条件之一:

  • 您在上一步中创建的文件的路径,如果 VM 具有现有的 SSH 密钥

  • 新 public SSH 密钥文件的路径,如果 VM 没有现有的 SSH 密钥

  1. 在主虚拟机中生成 ssh 密钥 ssh-keygen -o -C "mykey" -f ~/.ssh/id_rsa
  2. 然后在 gcp
  3. 的元数据部分复制 public 密钥
  4. 请确保在连接到同一实例时请使用该私钥

注意:不应安装 UFW