-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add GCE fingerprinting functionality #215
Conversation
This reads the following: * hostname * instance id * machine-type * zone * internal IP * external IP (if any) * tags * attributes Atributes are placed under the platform.gce.attr.* hierarchy. Tags are set up as platform.gce.tag.TagName=true.
GCE and AWS both expose metadata servers, and GCE's 404 response includes the URL in the content, which maatches the regex. So, check the response code as well and if a 4xx code comes back, take that to meanit's not AWS.
// provide their own | ||
metadataURL := os.Getenv("GCE_ENV_URL") | ||
if metadataURL == "" { | ||
metadataURL = "http://169.254.169.254/computeMetadata/v1/instance/" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you move this string to a const at the top and put a comment on it (make it look less like a magic value)
node.Links = make(map[string]string) | ||
} | ||
|
||
client := NewGCEMetadataClient(f.logger) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we put the client in the EnvGCEFingerprint struct so it doesn't have to be made twice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea. I originally did it that way so that the client wouldn't stay around forever once it was no longer needed, but I see that the Fingerprint objects aren't persistent anyway.
This allows easier reuse of the same client across multiple functions.
Above comments should be all taken care of. Just let me know if you have any others :) |
} | ||
|
||
// Get internal and external IP (if it exits) | ||
value, err := f.Get("network-interfaces/0/ip", false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want to look at all the attached network interfaces. So f.Get("network-interfaces/", true)
* No longer setting Device name in the network interface since we can't match up the info here with real device names. * Add attributes for all external IPs if more than one exists.
Some comments and outstanding questions on notable changes from the latest push:
FWIW I haven't been able to figure out how to actually attach more than 1 network to a GCE node so most of the above may be theoretical for now. |
I don't know what this means in GCE, but let me give you an example use-case to put this in context. In AWS some instances have enhanced networking, which makes the network device on the host directly available to the VM (it is not virtualized at all). This provides lower network latency. In Nomad I might want to schedule a latency-sensitive workload on these types of nodes. If the fingerprinter identifies the device type, I can use that information to make placement decisions.
In this scenario the fingerprinter that has more information (AWS or GCE in this case) should replace, update, or supplement data into the existing entry. This pattern means generic fingerprinters can run everywhere and provide baseline information, while more specialized fingerprinter can come in afterward and provide more detailed information.
Can you clarify the meaning of "network"? Is that a network subnet, or cidr range, or a security group, or just a GCE identifier? I would lean towards mirroring whatever the representation of this data is in GCE's API so it's more intuitive to write placement rules against it. |
In GCE, a "network" is pretty much the equivalent of an AWS VPC. That is, a subnet which is isolated from any other subnets, and with external access through external IPs, address translation, and security-group-like rules. An instance can only be in a single network; from what I've seen there's no way to create an instance in more than one network/subnet or with more than one interface. I haven't found any options that would expose another network device to the VM such as the AWS option you mentioned. I think things get confusing here because the GCE metadata API has provisions for instances with multiple network interfaces, and with multiple external IPs per network interface. This was probably done to be forward-compatible, but for now there will never be more than one of each. The main issue with supporting multiple network interfaces is that there isn't really a way to match up the interface for a network named SuggestionsThat said, with the current data available there isn't really any extra or better information to add to the Network resources that As for the external IP representation, you can see the full data format in the Mirroring it exactly would lead to something like |
* cpu-platform * scheduling.automatic-restart * scheduling.on-host-maintenance * network.NETWORKNAME=true
It has nothing to add that the generic fingerprinters aren't finding on their own already.
I see in |
metadataURL string | ||
} | ||
|
||
// NewEnvGCEFingerprint is used to create a CPU fingerprint |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update comment.
@dadgar seems like your last comment disappeared (deleted?) but here's the response I wrote: The data at that link is what's accessible through the full GCE API though, not through the metadata server, and we don't necessarily have access to the full API (I'm not sure if it's even possible without API keys). Unfortunately much less is exposed through the metadata server endpoints: https://cloud.google.com/compute/docs/metadata?hl=en As for the IPs, |
if err := json.Unmarshal([]byte(value), &interfaces); err != nil { | ||
f.logger.Printf("[WARN] fingerprint.env_gce: Error decoding network interface information: %s", err.Error()) | ||
} else { | ||
for _, intf := range interfaces { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dimfeld: Yeah I deleted because I realized exactly what you wrote. I spent some time reading the GCE docs and create an instance to play with and I agree with what you did in this PR. We will just use the network_unix.go. Just small comments and then we will merge this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool sounds great! Just took care of the one above.
Awesome! Thanks @dimfeld |
Add GCE fingerprinting functionality
Ensure installSnapshot consume stream. fixes issue hashicorp#212
I'm going to lock this pull request because it has been closed for 120 days ⏳. This helps our maintainers find and focus on the active contributions. |
Also fixes AWS fingerprinter to not run on GCE